Merge pull request #165 from varasev/update-finalization

(Fix) Finalization w/o reverts, some optimizations and refactoring
This commit is contained in:
Victor Baranov 2018-08-14 19:39:43 +03:00 committed by GitHub
commit ffe49f6b9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 108 additions and 104 deletions

View File

@ -262,15 +262,23 @@ export class BallotCard extends React.Component {
contract.address, contract.address,
contract.finalize(id), contract.finalize(id),
async tx => { async tx => {
this.isFinalized = true const events = await contract.instance.getPastEvents('BallotFinalized', {
ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized fromBlock: tx.blockNumber,
if (this.canBeFinalized !== null) { toBlock: tx.blockNumber
this.canBeFinalized = false
ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized
}
swal('Congratulations!', messages.FINALIZED_SUCCESS_MSG, 'success').then(result => {
push(`${commonStore.rootPath}`)
}) })
if (events.length > 0) {
this.isFinalized = true
ballotsStore.ballotCards[pos].props.votingState.isFinalized = this.isFinalized
if (this.canBeFinalized !== null) {
this.canBeFinalized = false
ballotsStore.ballotCards[pos].props.votingState.canBeFinalized = this.canBeFinalized
}
swal('Congratulations!', messages.FINALIZED_SUCCESS_MSG, 'success').then(result => {
push(`${commonStore.rootPath}`)
})
} else {
swal('Warning!', messages.INVALID_FINALIZE_MSG, 'warning')
}
}, },
messages.FINALIZE_FAILED_TX messages.FINALIZE_FAILED_TX
) )

View File

@ -218,9 +218,13 @@ export class NewBallot extends React.Component {
miningKey: ballotStore.ballotKeys.miningKey.value, miningKey: ballotStore.ballotKeys.miningKey.value,
ballotType: ballotStore.ballotKeys.keysBallotType ballotType: ballotStore.ballotKeys.keysBallotType
} }
let areBallotParamsValid = await contractsStore.votingToChangeKeys.areBallotParamsValid( let areBallotParamsValid
inputToAreBallotParamsValid areBallotParamsValid = await contractsStore.ballotsStorage.areKeysBallotParamsValid(inputToAreBallotParamsValid)
) if (areBallotParamsValid === null) {
areBallotParamsValid = await contractsStore.votingToChangeKeys.areBallotParamsValid(
inputToAreBallotParamsValid
)
}
if (ballotStore.ballotKeys.keysBallotType === ballotStore.KeysBallotType.add) { if (ballotStore.ballotKeys.keysBallotType === ballotStore.KeysBallotType.add) {
if (ballotStore.ballotKeys.keyType !== ballotStore.KeyType.mining) { if (ballotStore.ballotKeys.keyType !== ballotStore.KeyType.mining) {
if (!ballotStore.ballotKeys.miningKey.value) { if (!ballotStore.ballotKeys.miningKey.value) {
@ -239,7 +243,6 @@ export class NewBallot extends React.Component {
let methodToCreateBallot let methodToCreateBallot
let contractType let contractType
let contractInstance let contractInstance
//let web3 = new Web3(contractsStore.web3Instance.currentProvider)
switch (ballotStore.ballotType) { switch (ballotStore.ballotType) {
case ballotStore.BallotType.keys: case ballotStore.BallotType.keys:
methodToCreateBallot = this.createBallotForKeys methodToCreateBallot = this.createBallotForKeys
@ -343,16 +346,17 @@ export class NewBallot extends React.Component {
<div className="info"> <div className="info">
<p className="info-title">Information of the ballot</p> <p className="info-title">Information of the ballot</p>
<div className="info-i"> <div className="info-i">
Minimum {minThreshold} from {contractsStore.validatorsLength} validators required to pass the proposal<br /> Minimum {minThreshold} from {contractsStore.validatorsLength}
validators are required to pass the proposal<br />
</div> </div>
<div className="info-i"> <div className="info-i">
You can create {contractsStore.validatorLimits.keys} ballot for keys<br /> You can create {contractsStore.validatorLimits.keys} ballot(s) for keys<br />
</div> </div>
<div className="info-i"> <div className="info-i">
You can create {contractsStore.validatorLimits.minThreshold} ballot for consensus<br /> You can create {contractsStore.validatorLimits.minThreshold} ballot(s) for consensus<br />
</div> </div>
<div className="info-i"> <div className="info-i">
You can create {contractsStore.validatorLimits.proxy} ballot for proxy<br /> You can create {contractsStore.validatorLimits.proxy} ballot(s) for proxy<br />
</div> </div>
</div> </div>
</div> </div>

View File

@ -6,11 +6,20 @@ export default class BallotsStorage {
async init({ web3, netId }) { async init({ web3, netId }) {
const { BALLOTS_STORAGE_ADDRESS } = networkAddresses(netId) const { BALLOTS_STORAGE_ADDRESS } = networkAddresses(netId)
console.log('Ballots Storage address', BALLOTS_STORAGE_ADDRESS) console.log('Ballots Storage address', BALLOTS_STORAGE_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let ballotsStorageAbi = await helpers.getABI(branch, 'BallotStorage') const ballotsStorageAbi = await helpers.getABI(branch, 'BallotStorage')
this.ballotsStorageInstance = new web3_10.eth.Contract(ballotsStorageAbi, BALLOTS_STORAGE_ADDRESS) this.ballotsStorageInstance = new web3_10.eth.Contract(ballotsStorageAbi, BALLOTS_STORAGE_ADDRESS)
} }
areKeysBallotParamsValid({ ballotType, affectedKey, affectedKeyType, miningKey }) {
if (!this.ballotsStorageInstance.methods.areKeysBallotParamsValid) {
return null
}
return this.ballotsStorageInstance.methods
.areKeysBallotParamsValid(ballotType, affectedKey, affectedKeyType, miningKey)
.call()
}
} }

View File

@ -0,0 +1,18 @@
import Web3 from 'web3'
import { networkAddresses } from './addresses'
import helpers from './helpers'
export default class KeysManager {
async init({ web3, netId }) {
const { KEYS_MANAGER_ADDRESS } = networkAddresses(netId)
console.log('KeysManager address', KEYS_MANAGER_ADDRESS)
const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId)
const keysManagerABI = await helpers.getABI(branch, 'KeysManager')
this.instance = new web3_10.eth.Contract(keysManagerABI, KEYS_MANAGER_ADDRESS)
this.address = KEYS_MANAGER_ADDRESS
}
}

View File

@ -6,11 +6,11 @@ export default class POAConsensus {
async init({ web3, netId }) { async init({ web3, netId }) {
const { POA_ADDRESS } = networkAddresses(netId) const { POA_ADDRESS } = networkAddresses(netId)
console.log('POA address', POA_ADDRESS) console.log('POA address', POA_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let poaConsensusAbi = await helpers.getABI(branch, 'PoaNetworkConsensus') const poaConsensusAbi = await helpers.getABI(branch, 'PoaNetworkConsensus')
this.poaInstance = new web3_10.eth.Contract(poaConsensusAbi, POA_ADDRESS) this.poaInstance = new web3_10.eth.Contract(poaConsensusAbi, POA_ADDRESS)
} }

View File

@ -6,10 +6,10 @@ export default class ProxyStorage {
async init({ web3, netId }) { async init({ web3, netId }) {
const { PROXY_ADDRESS } = networkAddresses(netId) const { PROXY_ADDRESS } = networkAddresses(netId)
console.log('Proxy Storage address', PROXY_ADDRESS) console.log('Proxy Storage address', PROXY_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let proxyStorageAbi = await helpers.getABI(branch, 'ProxyStorage') const proxyStorageAbi = await helpers.getABI(branch, 'ProxyStorage')
this.proxyStorageInstance = new web3_10.eth.Contract(proxyStorageAbi, PROXY_ADDRESS) this.proxyStorageInstance = new web3_10.eth.Contract(proxyStorageAbi, PROXY_ADDRESS)
} }

View File

@ -7,17 +7,16 @@ export default class ValidatorMetadata {
async init({ web3, netId }) { async init({ web3, netId }) {
const { METADATA_ADDRESS } = networkAddresses(netId) const { METADATA_ADDRESS } = networkAddresses(netId)
console.log('Metadata address', METADATA_ADDRESS) console.log('Metadata address', METADATA_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let MetadataAbi = await helpers.getABI(branch, 'ValidatorMetadata') const MetadataAbi = await helpers.getABI(branch, 'ValidatorMetadata')
this.metadataInstance = new web3_10.eth.Contract(MetadataAbi, METADATA_ADDRESS) this.metadataInstance = new web3_10.eth.Contract(MetadataAbi, METADATA_ADDRESS)
} }
async getValidatorFullName({ votingKey, miningKey }) { async getValidatorFullName(miningKey) {
miningKey = miningKey || (await this.getMiningByVoting(votingKey))
let validator let validator
if (this.metadataInstance.methods.getValidatorName) { if (this.metadataInstance.methods.getValidatorName) {
validator = await this.metadataInstance.methods.getValidatorName(miningKey).call() validator = await this.metadataInstance.methods.getValidatorName(miningKey).call()
@ -29,8 +28,4 @@ export default class ValidatorMetadata {
lastName: toAscii(validator.lastName) lastName: toAscii(validator.lastName)
} }
} }
async getMiningByVoting(votingKey) {
return await this.metadataInstance.methods.getMiningByVotingKey(votingKey).call()
}
} }

View File

@ -6,15 +6,16 @@ export default class VotingToChangeKeys {
async init({ web3, netId }) { async init({ web3, netId }) {
const { VOTING_TO_CHANGE_KEYS_ADDRESS } = networkAddresses(netId) const { VOTING_TO_CHANGE_KEYS_ADDRESS } = networkAddresses(netId)
console.log('VotingToChangeKeys address', VOTING_TO_CHANGE_KEYS_ADDRESS) console.log('VotingToChangeKeys address', VOTING_TO_CHANGE_KEYS_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let votingToChangeKeysABI = await helpers.getABI(branch, 'VotingToChangeKeys') const votingToChangeKeysABI = await helpers.getABI(branch, 'VotingToChangeKeys')
this.votingToChangeKeysInstance = new web3_10.eth.Contract(votingToChangeKeysABI, VOTING_TO_CHANGE_KEYS_ADDRESS) this.votingToChangeKeysInstance = new web3_10.eth.Contract(votingToChangeKeysABI, VOTING_TO_CHANGE_KEYS_ADDRESS)
this.gasPrice = web3_10.utils.toWei('1', 'gwei') this.gasPrice = web3_10.utils.toWei('1', 'gwei')
this.address = VOTING_TO_CHANGE_KEYS_ADDRESS this.address = VOTING_TO_CHANGE_KEYS_ADDRESS
this.instance = this.votingToChangeKeysInstance
} }
//setters //setters
@ -44,6 +45,9 @@ export default class VotingToChangeKeys {
//getters //getters
areBallotParamsValid({ ballotType, affectedKey, affectedKeyType, miningKey }) { areBallotParamsValid({ ballotType, affectedKey, affectedKeyType, miningKey }) {
if (!this.doesMethodExist('areBallotParamsValid')) {
return null
}
return this.votingToChangeKeysInstance.methods return this.votingToChangeKeysInstance.methods
.areBallotParamsValid(ballotType, affectedKey, affectedKeyType, miningKey) .areBallotParamsValid(ballotType, affectedKey, affectedKeyType, miningKey)
.call() .call()
@ -83,22 +87,8 @@ export default class VotingToChangeKeys {
return null return null
} }
getMiningByVotingKey(_votingKey) { async getBallotLimit(_miningKey, _limitPerValidator) {
return this.votingToChangeKeysInstance.methods.getMiningByVotingKey(_votingKey).call() const _activeBallots = await this.votingToChangeKeysInstance.methods.validatorActiveBallots(_miningKey).call()
} return _limitPerValidator - _activeBallots
async getValidatorActiveBallots(_votingKey) {
let miningKey
try {
miningKey = await this.getMiningByVotingKey(_votingKey)
} catch (e) {
miningKey = '0x0000000000000000000000000000000000000000'
}
return await this.votingToChangeKeysInstance.methods.validatorActiveBallots(miningKey).call()
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeKeysInstance.methods.getBallotLimitPerValidator().call()
return currentLimit - (await this.getValidatorActiveBallots(_votingKey))
} }
} }

View File

@ -6,11 +6,11 @@ export default class VotingToChangeMinThreshold {
async init({ web3, netId }) { async init({ web3, netId }) {
const { VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS } = networkAddresses(netId) const { VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS } = networkAddresses(netId)
console.log('VotingToChangeMinThreshold address', VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS) console.log('VotingToChangeMinThreshold address', VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let votingToChangeMinThresholdABI = await helpers.getABI(branch, 'VotingToChangeMinThreshold') const votingToChangeMinThresholdABI = await helpers.getABI(branch, 'VotingToChangeMinThreshold')
this.votingToChangeMinThresholdInstance = new web3_10.eth.Contract( this.votingToChangeMinThresholdInstance = new web3_10.eth.Contract(
votingToChangeMinThresholdABI, votingToChangeMinThresholdABI,
@ -18,6 +18,7 @@ export default class VotingToChangeMinThreshold {
) )
this.gasPrice = web3_10.utils.toWei('1', 'gwei') this.gasPrice = web3_10.utils.toWei('1', 'gwei')
this.address = VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS this.address = VOTING_TO_CHANGE_MIN_THRESHOLD_ADDRESS
this.instance = this.votingToChangeMinThresholdInstance
} }
//setters //setters
@ -77,22 +78,10 @@ export default class VotingToChangeMinThreshold {
return null return null
} }
getMiningByVotingKey(_votingKey) { async getBallotLimit(_miningKey, _limitPerValidator) {
return this.votingToChangeMinThresholdInstance.methods.getMiningByVotingKey(_votingKey).call() const _activeBallots = await this.votingToChangeMinThresholdInstance.methods
} .validatorActiveBallots(_miningKey)
.call()
async getValidatorActiveBallots(_votingKey) { return _limitPerValidator - _activeBallots
let miningKey
try {
miningKey = await this.getMiningByVotingKey(_votingKey)
} catch (e) {
miningKey = '0x0000000000000000000000000000000000000000'
}
return await this.votingToChangeMinThresholdInstance.methods.validatorActiveBallots(miningKey).call()
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeMinThresholdInstance.methods.getBallotLimitPerValidator().call()
return currentLimit - (await this.getValidatorActiveBallots(_votingKey))
} }
} }

View File

@ -6,15 +6,16 @@ export default class VotingToChangeProxy {
async init({ web3, netId }) { async init({ web3, netId }) {
const { VOTING_TO_CHANGE_PROXY_ADDRESS } = networkAddresses(netId) const { VOTING_TO_CHANGE_PROXY_ADDRESS } = networkAddresses(netId)
console.log('VotingToChangeProxy address', VOTING_TO_CHANGE_PROXY_ADDRESS) console.log('VotingToChangeProxy address', VOTING_TO_CHANGE_PROXY_ADDRESS)
let web3_10 = new Web3(web3.currentProvider) const web3_10 = new Web3(web3.currentProvider)
const branch = helpers.getBranch(netId) const branch = helpers.getBranch(netId)
let votingToChangeProxyABI = await helpers.getABI(branch, 'VotingToChangeProxyAddress') const votingToChangeProxyABI = await helpers.getABI(branch, 'VotingToChangeProxyAddress')
this.votingToChangeProxyInstance = new web3_10.eth.Contract(votingToChangeProxyABI, VOTING_TO_CHANGE_PROXY_ADDRESS) this.votingToChangeProxyInstance = new web3_10.eth.Contract(votingToChangeProxyABI, VOTING_TO_CHANGE_PROXY_ADDRESS)
this.gasPrice = web3_10.utils.toWei('1', 'gwei') this.gasPrice = web3_10.utils.toWei('1', 'gwei')
this.address = VOTING_TO_CHANGE_PROXY_ADDRESS this.address = VOTING_TO_CHANGE_PROXY_ADDRESS
this.instance = this.votingToChangeProxyInstance
} }
//setters //setters
@ -74,22 +75,8 @@ export default class VotingToChangeProxy {
return null return null
} }
getMiningByVotingKey(_votingKey) { async getBallotLimit(_miningKey, _limitPerValidator) {
return this.votingToChangeProxyInstance.methods.getMiningByVotingKey(_votingKey).call() const _activeBallots = await this.votingToChangeProxyInstance.methods.validatorActiveBallots(_miningKey).call()
} return _limitPerValidator - _activeBallots
async getValidatorActiveBallots(_votingKey) {
let miningKey
try {
miningKey = await this.getMiningByVotingKey(_votingKey)
} catch (e) {
miningKey = '0x0000000000000000000000000000000000000000'
}
return await this.votingToChangeProxyInstance.methods.validatorActiveBallots(miningKey).call()
}
async getBallotLimit(_votingKey) {
const currentLimit = await this.votingToChangeProxyInstance.methods.getBallotLimitPerValidator().call()
return currentLimit - (await this.getValidatorActiveBallots(_votingKey))
} }
} }

View File

@ -41,6 +41,7 @@ class AppMainRouter extends Component {
let setPoaConsensus = contractsStore.setPoaConsensus(web3Config) let setPoaConsensus = contractsStore.setPoaConsensus(web3Config)
let setBallotsStorage = contractsStore.setBallotsStorage(web3Config) let setBallotsStorage = contractsStore.setBallotsStorage(web3Config)
let setKeysManager = contractsStore.setKeysManager(web3Config)
let setProxyStorage = contractsStore.setProxyStorage(web3Config) let setProxyStorage = contractsStore.setProxyStorage(web3Config)
let setVotingToChangeKeys = contractsStore.setVotingToChangeKeys(web3Config) let setVotingToChangeKeys = contractsStore.setVotingToChangeKeys(web3Config)
let setVotingToChangeMinThreshold = contractsStore.setVotingToChangeMinThreshold(web3Config) let setVotingToChangeMinThreshold = contractsStore.setVotingToChangeMinThreshold(web3Config)
@ -50,6 +51,7 @@ class AppMainRouter extends Component {
await Promise.all([ await Promise.all([
setPoaConsensus, setPoaConsensus,
setBallotsStorage, setBallotsStorage,
setKeysManager,
setProxyStorage, setProxyStorage,
setVotingToChangeKeys, setVotingToChangeKeys,
setVotingToChangeMinThreshold, setVotingToChangeMinThreshold,

View File

@ -3,6 +3,7 @@ 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 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'
@ -21,6 +22,7 @@ import 'babel-polyfill'
class ContractsStore { class ContractsStore {
@observable poaConsensus @observable poaConsensus
@observable ballotsStorage @observable ballotsStorage
@observable keysManager
@observable proxyStorage @observable proxyStorage
@observable votingToChangeKeys @observable votingToChangeKeys
@observable votingToChangeMinThreshold @observable votingToChangeMinThreshold
@ -90,6 +92,15 @@ class ContractsStore {
}) })
} }
@action('Set KeysManager contract')
setKeysManager = async web3Config => {
this.keysManager = new KeysManager()
await this.keysManager.init({
web3: web3Config.web3Instance,
netId: web3Config.netId
})
}
@action('Set ProxyStorage contract') @action('Set ProxyStorage contract')
setProxyStorage = async web3Config => { setProxyStorage = async web3Config => {
this.proxyStorage = new ProxyStorage() this.proxyStorage = new ProxyStorage()
@ -148,9 +159,7 @@ class ContractsStore {
@action('Set mining key') @action('Set mining key')
setMiningKey = async web3Config => { setMiningKey = async web3Config => {
try { try {
this.miningKey = await this.votingToChangeKeys.votingToChangeKeysInstance.methods this.miningKey = await this.keysManager.instance.methods.miningKeyByVoting(web3Config.defaultAccount).call()
.getMiningByVotingKey(web3Config.defaultAccount)
.call()
} catch (e) { } catch (e) {
console.log(e) console.log(e)
this.miningKey = '0x0000000000000000000000000000000000000000' this.miningKey = '0x0000000000000000000000000000000000000000'
@ -329,20 +338,13 @@ class ContractsStore {
@action @action
async getBallotsLimits() { async getBallotsLimits() {
if (this.web3Instance && this.netId) { if (this.web3Instance && this.netId) {
let setVotingToChangeKeys = this.setVotingToChangeKeys({ web3Instance: this.web3Instance, netId: this.netId }) const limitPerValidator = await this.ballotsStorage.ballotsStorageInstance.methods
let setVotingToChangeMinThreshold = this.setVotingToChangeMinThreshold({ .getBallotLimitPerValidator()
web3Instance: this.web3Instance, .call()
netId: this.netId
})
let setVotingToChangeProxy = this.setVotingToChangeProxy({ web3Instance: this.web3Instance, netId: this.netId })
await Promise.all([setVotingToChangeKeys, setVotingToChangeMinThreshold, setVotingToChangeProxy]) let getKeysLimit = await this.votingToChangeKeys.getBallotLimit(this.miningKey, limitPerValidator)
let getMinThresholdLimit = await this.votingToChangeMinThreshold.getBallotLimit(this.miningKey, limitPerValidator)
let getKeysLimit = await this.votingToChangeKeys.getBallotLimit(this.web3Instance.eth.defaultAccount) let getProxyLimit = await this.votingToChangeProxy.getBallotLimit(this.miningKey, limitPerValidator)
let getMinThresholdLimit = await this.votingToChangeMinThreshold.getBallotLimit(
this.web3Instance.eth.defaultAccount
)
let getProxyLimit = await this.votingToChangeProxy.getBallotLimit(this.web3Instance.eth.defaultAccount)
await Promise.all([getKeysLimit, getMinThresholdLimit, getProxyLimit]).then( await Promise.all([getKeysLimit, getMinThresholdLimit, getProxyLimit]).then(
([keysLimit, minThresholdLimit, proxyLimit]) => { ([keysLimit, minThresholdLimit, proxyLimit]) => {
@ -360,7 +362,7 @@ class ContractsStore {
const keys = await this.poaConsensus.getValidators() const keys = await this.poaConsensus.getValidators()
this.validatorsLength = keys.length this.validatorsLength = keys.length
keys.forEach(async key => { keys.forEach(async key => {
const metadata = await this.validatorMetadata.getValidatorFullName({ miningKey: key }) const metadata = await this.validatorMetadata.getValidatorFullName(key)
this.validatorsMetadata[key.toLowerCase()] = { this.validatorsMetadata[key.toLowerCase()] = {
label: `${key} ${metadata.lastName}`, label: `${key} ${metadata.lastName}`,
lastNameAndKey: `${metadata.lastName} ${key}`, lastNameAndKey: `${metadata.lastName} ${key}`,