Fetch validators' confirmed address based on confirm event data.

Get confirmed addresses by the kekkakIdentifier in LogAddressConfirmed
event from PoPA.
Improve eventual exception handling in AllValidators' validator address
augmentation.
This commit is contained in:
Jorge Shirai 2018-08-29 13:31:52 -03:00
parent c940f674f1
commit ea55e88981
2 changed files with 62 additions and 95 deletions

View File

@ -43,23 +43,28 @@ export default class AllValidators extends Component {
if (popa === null) {
return validators
}
const validatorsWithConfirmAddressEvent = await popa.filterValidatorsWithConfirmAddressEvent(validators)
const getConfirmedAddressesPromises = validatorsWithConfirmAddressEvent.map(validator => {
return popa.getUserConfirmedAddresses(validator.address).then(confirmedAddresses => {
// Only augment a validator if PoPA returned a confirmed address
if (confirmedAddresses.length > 0) {
const validatorConfirmedAddress = {
fullAddress: `${confirmedAddresses[0].location} ${confirmedAddresses[0].city}`,
us_state: confirmedAddresses[0].state,
postal_code: confirmedAddresses[0].zip,
isAddressConfirmed: true
// Until everything is done ok, result will be validators
let result = validators
try {
const getConfirmedAddressesPromises = validators.map(validator => {
return popa.getUserConfirmedAddresses(validator.address).then(confirmedAddresses => {
let validatorConfirmedAddress = {}
if (confirmedAddresses.length > 0) {
validatorConfirmedAddress = {
fullAddress: `${confirmedAddresses[0].location} ${confirmedAddresses[0].city}`,
us_state: confirmedAddresses[0].state,
postal_code: confirmedAddresses[0].zip,
isAddressConfirmed: true
}
}
Object.assign(validator, validatorConfirmedAddress)
}
return Object.assign({}, validator, validatorConfirmedAddress)
})
})
})
return Promise.all(getConfirmedAddressesPromises).then(() => validators)
result = await Promise.all(getConfirmedAddressesPromises)
} catch (e) {
console.error('Error while augmenting validators with confirmed address', e)
}
return result
}
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.web3Config.netId !== this.state.netId) {

View File

@ -15,41 +15,11 @@ export default class ProofOfPhysicalAddress {
let proofOfPhysicalAddressAbi = await helpers.getABI(branch, 'ProofOfPhysicalAddress')
this.instance = new web3_10.eth.Contract(proofOfPhysicalAddressAbi, PROOF_OF_PHYSICAL_ADDRESS)
this.filterValidatorsWithConfirmAddressEvent = this.filterValidatorsWithConfirmAddressEvent.bind(this)
this.getAddressesCount = this.getAddressesCount.bind(this)
this.getUserConfirmedAddresses = this.getUserConfirmedAddresses.bind(this)
this.getAddressIndexAndConfirmationStatus = this.getAddressIndexAndConfirmationStatus.bind(this)
this.getPhysicalAddressesByIndexes = this.getPhysicalAddressesByIndexes.bind(this)
this.getAllEvents = this.getAllEvents.bind(this)
}
/**
* Filter the given validators array by leaving only the elements whose wallet address generated,
* at least, one PoPA LogAddressConfirmed event.
* @param {Object[]} validatorArray
* @return {Object[]}
*/
async filterValidatorsWithConfirmAddressEvent(validatorArray) {
const confirmAddressEvents = await this.getAllEvents(CONFIRM_ADDRESS_EVENT_NAME)
const validatorArrayWithConfirmedAddress = validatorArray.filter(validator => {
const hasConfirmedAddress = confirmAddressEvents.some(
confirmAddressEvent => confirmAddressEvent.returnValues.wallet === validator.address
)
return hasConfirmedAddress
})
return validatorArrayWithConfirmedAddress
}
/**
* Resolves to the number of confimed physical addresses of the given wallet address.
* @param {String} walletAddress
* @param {boolean} walletAddress
* @return {Promise}
*/
async getAddressesCount(walletAddress, getUserConfirmed) {
const method = getUserConfirmed ? 'userConfirmedAddressesCount' : 'userSubmittedAddressesCount'
const count = await this.instance.methods[method](walletAddress).call()
return Number.parseInt(count, 10)
this.getConfirmedAddressesByWalletAddressAndKeccakIdentifierArray = this.getConfirmedAddressesByWalletAddressAndKeccakIdentifierArray.bind(
this
)
}
/**
@ -61,18 +31,16 @@ export default class ProofOfPhysicalAddress {
async getUserConfirmedAddresses(walletAddress) {
let result = []
try {
// Get an array representing index => isConfirmed
const confirmedCount = await this.getAddressesCount(walletAddress, true)
if (confirmedCount > 0) {
const addressConfirmedStatuses = await this.getAddressIndexAndConfirmationStatus(walletAddress, confirmedCount)
// Convert an array of indexes of confirmed-addresses-only (i.e. [3,7])
let addressConfirmedIndexes = []
addressConfirmedStatuses.forEach((isConfirmed, index) => {
if (isConfirmed) {
addressConfirmedIndexes.push(index)
}
})
result = await this.getPhysicalAddressesByIndexes(walletAddress, addressConfirmedIndexes)
const confirmAddressEvents = await this.getAllEvents(CONFIRM_ADDRESS_EVENT_NAME)
let keccakIdentifiers = confirmAddressEvents
.filter(event => event.returnValues.wallet === walletAddress)
.map(event => event.returnValues.keccakIdentifier)
if (keccakIdentifiers.length > 0) {
let physicalAddresses = await this.getConfirmedAddressesByWalletAddressAndKeccakIdentifierArray(
walletAddress,
keccakIdentifiers
)
result = physicalAddresses.length > 0 ? physicalAddresses : result
}
} catch (e) {
console.error(`Error in getUserConfirmedAddresses ${walletAddress}`, e)
@ -82,43 +50,37 @@ export default class ProofOfPhysicalAddress {
}
/**
* Resolves to an array with the confirmed status of the address in the
* corresponding PhysicalAddress[] index (in the contract).
* @param {String} walletAddress
* @param {Integer} submittedCount
* Given a walletAddress and an array of keccakIdentifiers, return a promise that resolves to an array
* of the corresponding confirmed physical addresses, or an empty array.
* @param {String} walletAddress
* @param {String[]} keccakIdentifierArray
* @return {Promise}
*/
async getAddressIndexAndConfirmationStatus(walletAddress, submittedCount) {
try {
let promises = []
for (let i = 0; i < submittedCount; i++) {
promises.push(this.instance.methods.userAddressConfirmed(walletAddress, i).call())
}
return await Promise.all(promises)
} catch (e) {
console.log(`Error getAddressIndexAndConfirmationStatus(${walletAddress}, ${submittedCount})`, e)
throw e
}
}
/**
* Resolves to an array of PhysicalAddress representation (check the contract
* ABI). Each PhysicalAddress is fetch by its wallet address and its
* corresponding index.
* @param {String} walletAddress
* @param {[Integer]} physicalAddressIndexesArray
* @return {Promise}
*/
async getPhysicalAddressesByIndexes(walletAddress, physicalAddressIndexesArray) {
try {
const promises = physicalAddressIndexesArray.map(physicalAddressIndex =>
this.instance.methods.userAddress(walletAddress, physicalAddressIndex).call()
)
return await Promise.all(promises)
} catch (e) {
console.log(`Error getPhysicalAddressesByIndexes(${walletAddress}, ${physicalAddressIndexesArray})`, e)
throw e
}
async getConfirmedAddressesByWalletAddressAndKeccakIdentifierArray(walletAddress, keccakIdentifierArray) {
let promises = keccakIdentifierArray.map(keccakIdentifier => {
return this.instance.methods
.userAddressByKeccakIdentifier(walletAddress, keccakIdentifier)
.call()
.then(addressStatusTuple => {
const addressFound = addressStatusTuple[0]
const addressIndex = addressStatusTuple[1]
const addressConfirmed = addressStatusTuple[2]
// If addressIndex === 0, it also means the address was not found
if (addressFound === false || addressIndex === 0) {
return null
} else {
return addressConfirmed === true
? this.instance.methods.userAddress(walletAddress, addressIndex).call()
: null
}
})
.catch(e => {
console.error(`Error in getAddressesByWalletAddressAndKeccakIdentifierArray`, e)
return null
})
})
let physicalAddressArray = await Promise.all(promises)
return physicalAddressArray.filter(address => address !== null)
}
/**