2018-07-11 08:50:14 -07:00
|
|
|
import React, { Component } from 'react'
|
|
|
|
import './stylesheets/application.css'
|
|
|
|
import PlacesAutocomplete, { geocodeByAddress } from 'react-places-autocomplete'
|
|
|
|
import moment from 'moment'
|
|
|
|
import Loading from './Loading'
|
|
|
|
import { messages } from './messages'
|
|
|
|
import helpers from './helpers'
|
|
|
|
import { constants } from './constants'
|
2017-12-11 17:35:57 -08:00
|
|
|
|
|
|
|
class App extends Component {
|
2018-07-11 08:50:14 -07:00
|
|
|
constructor(props) {
|
|
|
|
super(props)
|
2017-12-11 17:35:57 -08:00
|
|
|
this.checkValidation = this.checkValidation.bind(this)
|
2018-07-11 08:50:14 -07:00
|
|
|
this.onClick = this.onClick.bind(this)
|
|
|
|
this.onChangeFormField = this.onChangeFormField.bind(this)
|
|
|
|
this.getKeysManager = this.getKeysManager.bind(this)
|
|
|
|
this.getMetadataContract = this.getMetadataContract.bind(this)
|
|
|
|
this.getVotingKey = this.getVotingKey.bind(this)
|
|
|
|
this.onChangeAutoComplete = address => {
|
|
|
|
const form = this.state.form
|
|
|
|
form.fullAddress = address
|
|
|
|
this.setState({ form })
|
|
|
|
}
|
2017-12-11 17:35:57 -08:00
|
|
|
this.onSelect = this.onSelectAutocomplete.bind(this)
|
|
|
|
this.state = {
|
|
|
|
web3Config: {},
|
|
|
|
form: {
|
|
|
|
fullAddress: '',
|
|
|
|
expirationDate: '',
|
|
|
|
postal_code: '',
|
|
|
|
us_state: '',
|
|
|
|
firstName: '',
|
|
|
|
lastName: '',
|
|
|
|
licenseId: ''
|
|
|
|
},
|
|
|
|
hasData: false
|
|
|
|
}
|
|
|
|
|
2018-07-11 08:50:14 -07:00
|
|
|
this.defaultValues = null
|
|
|
|
this.setMetadata.call(this)
|
2018-01-31 13:24:52 -08:00
|
|
|
|
2018-07-11 08:56:38 -07:00
|
|
|
this.isValidVotingKey = false
|
|
|
|
this.setIsValidVotingKey.call(this)
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
async setMetadata() {
|
|
|
|
const currentData = await this.getMetadataContract().getValidatorData({
|
|
|
|
votingKey: this.getVotingKey()
|
|
|
|
})
|
2018-04-11 03:59:50 -07:00
|
|
|
const hasData = currentData.postal_code ? true : false
|
2018-07-11 08:50:14 -07:00
|
|
|
this.defaultValues = currentData
|
|
|
|
const pendingChange = await this.getMetadataContract().getPendingChange({
|
|
|
|
votingKey: this.getVotingKey()
|
|
|
|
})
|
|
|
|
if (Number(pendingChange.minThreshold) > 0) {
|
2018-03-12 11:41:19 -07:00
|
|
|
var msg = `
|
|
|
|
First Name: <b>${pendingChange.firstName}</b> <br/>
|
|
|
|
Last Name: <b>${pendingChange.lastName}</b> <br/>
|
|
|
|
Full Address: <b>${pendingChange.fullAddress}</b> <br/>
|
|
|
|
Expiration Date: <b>${pendingChange.expirationDate}</b> <br />
|
|
|
|
License ID: <b>${pendingChange.licenseId}</b> <br/>
|
|
|
|
US state: <b>${pendingChange.us_state}</b> <br/>
|
|
|
|
Zip Code: <b>${pendingChange.postal_code}</b> <br/>
|
2018-07-11 08:50:14 -07:00
|
|
|
`
|
|
|
|
helpers.generateAlert('warning', 'You have pending changes!', msg)
|
2017-12-12 23:27:31 -08:00
|
|
|
}
|
2017-12-11 23:01:59 -08:00
|
|
|
this.setState({
|
|
|
|
form: {
|
2017-12-12 01:25:19 -08:00
|
|
|
fullAddress: currentData.fullAddress,
|
|
|
|
expirationDate: currentData.expirationDate,
|
|
|
|
postal_code: currentData.postal_code,
|
|
|
|
us_state: currentData.us_state,
|
|
|
|
firstName: currentData.firstName,
|
|
|
|
lastName: currentData.lastName,
|
2018-07-11 08:50:14 -07:00
|
|
|
licenseId: currentData.licenseId
|
2017-12-11 23:01:59 -08:00
|
|
|
},
|
|
|
|
hasData
|
2018-07-11 08:50:14 -07:00
|
|
|
})
|
2017-12-11 23:01:59 -08:00
|
|
|
}
|
2018-07-06 00:05:26 -07:00
|
|
|
async setIsValidVotingKey() {
|
2018-07-11 08:56:38 -07:00
|
|
|
this.isValidVotingKey = await this.getKeysManager().isVotingActive(this.getVotingKey())
|
2018-07-06 00:05:26 -07:00
|
|
|
if (!this.isValidVotingKey) {
|
2018-07-11 08:56:38 -07:00
|
|
|
helpers.generateAlert('warning', 'Warning!', messages.invalidaVotingKey)
|
2018-07-06 00:05:26 -07:00
|
|
|
}
|
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
getKeysManager() {
|
|
|
|
return this.props.web3Config.keysManager
|
2017-12-11 23:01:59 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
getMetadataContract() {
|
|
|
|
return this.props.web3Config.metadataContract
|
2017-12-11 23:01:59 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
getVotingKey() {
|
|
|
|
return this.props.web3Config.votingKey
|
2017-12-11 23:01:59 -08:00
|
|
|
}
|
2017-12-11 17:35:57 -08:00
|
|
|
checkValidation() {
|
2018-07-11 08:50:14 -07:00
|
|
|
const isAfter = moment(this.state.form.expirationDate).isAfter(moment())
|
|
|
|
let keys = Object.keys(this.state.form)
|
|
|
|
keys.forEach(key => {
|
|
|
|
if (!this.state.form[key]) {
|
|
|
|
this.setState({ loading: false })
|
|
|
|
helpers.generateAlert('warning', 'Warning!', `${key} cannot be empty`)
|
|
|
|
return false
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
})
|
2018-07-11 08:50:14 -07:00
|
|
|
if (isAfter) {
|
2017-12-11 17:35:57 -08:00
|
|
|
} else {
|
2018-07-11 08:50:14 -07:00
|
|
|
this.setState({ loading: false })
|
|
|
|
helpers.generateAlert('warning', 'Warning!', 'Expiration date should be valid')
|
|
|
|
return false
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
return true
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
async onSelectAutocomplete(data) {
|
|
|
|
let place = await geocodeByAddress(data)
|
2018-07-11 08:50:14 -07:00
|
|
|
let address_components = {}
|
2017-12-11 17:35:57 -08:00
|
|
|
for (var i = 0; i < place[0].address_components.length; i++) {
|
2018-07-11 08:50:14 -07:00
|
|
|
var addressType = place[0].address_components[i].types[0]
|
|
|
|
switch (addressType) {
|
|
|
|
case 'postal_code':
|
|
|
|
address_components.postal_code = place[0].address_components[i].short_name
|
|
|
|
break
|
|
|
|
case 'street_number':
|
|
|
|
address_components.street_number = place[0].address_components[i].short_name
|
|
|
|
break
|
|
|
|
case 'route':
|
|
|
|
address_components.route = place[0].address_components[i].short_name
|
|
|
|
break
|
|
|
|
case 'locality':
|
|
|
|
address_components.locality = place[0].address_components[i].short_name
|
|
|
|
break
|
|
|
|
case 'administrative_area_level_1':
|
|
|
|
address_components.administrative_area_level_1 = place[0].address_components[i].short_name
|
|
|
|
break
|
2018-02-26 06:35:10 -08:00
|
|
|
default:
|
2018-07-11 08:50:14 -07:00
|
|
|
break
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
let form = this.state.form
|
|
|
|
form.fullAddress = `${address_components.street_number} ${address_components.route} ${
|
|
|
|
address_components.locality
|
|
|
|
}`
|
|
|
|
form.us_state = address_components.administrative_area_level_1
|
|
|
|
form.postal_code = address_components.postal_code
|
2017-12-11 17:35:57 -08:00
|
|
|
this.setState({
|
|
|
|
form
|
2018-07-11 08:50:14 -07:00
|
|
|
})
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
async onClick() {
|
2018-07-11 08:50:14 -07:00
|
|
|
this.setState({ loading: true })
|
|
|
|
const isFormValid = this.checkValidation()
|
|
|
|
if (isFormValid) {
|
|
|
|
const votingKey = this.getVotingKey()
|
2017-12-12 01:25:19 -08:00
|
|
|
console.log('voting', votingKey)
|
2018-07-11 08:50:14 -07:00
|
|
|
const isValid = await this.getKeysManager().isVotingActive(votingKey)
|
|
|
|
console.log(isValid)
|
|
|
|
if (isValid) {
|
|
|
|
// // add loading screen
|
2017-12-12 01:25:19 -08:00
|
|
|
await this.sendTxToContract()
|
|
|
|
} else {
|
2018-07-11 08:50:14 -07:00
|
|
|
this.setState({ loading: false })
|
|
|
|
helpers.generateAlert('warning', 'Warning!', messages.invalidaVotingKey)
|
|
|
|
return
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
async sendTxToContract() {
|
|
|
|
this.getMetadataContract()
|
|
|
|
.createMetadata({
|
|
|
|
firstName: this.state.form.firstName,
|
|
|
|
lastName: this.state.form.lastName,
|
|
|
|
licenseId: this.state.form.licenseId,
|
|
|
|
fullAddress: this.state.form.fullAddress,
|
|
|
|
state: this.state.form.us_state,
|
|
|
|
zipcode: this.state.form.postal_code,
|
|
|
|
expirationDate: moment(this.state.form.expirationDate).unix(),
|
|
|
|
votingKey: this.getVotingKey(),
|
|
|
|
hasData: this.state.hasData
|
|
|
|
})
|
|
|
|
.then(receipt => {
|
|
|
|
console.log(receipt)
|
|
|
|
this.setState({ loading: false })
|
|
|
|
helpers.generateAlert('success', 'Congratulations!', 'Your metadata was sent!')
|
|
|
|
})
|
|
|
|
.catch(error => {
|
|
|
|
console.error(error.message)
|
|
|
|
let errDescription
|
|
|
|
if (error.message.includes(constants.userDeniedTransactionPattern))
|
|
|
|
errDescription = `Error: User ${constants.userDeniedTransactionPattern}`
|
|
|
|
else errDescription = error.message
|
|
|
|
this.setState({ loading: false })
|
|
|
|
var msg = `
|
2018-01-31 13:24:52 -08:00
|
|
|
Something went wrong!<br/><br/>
|
2018-03-12 11:41:19 -07:00
|
|
|
${errDescription}
|
2018-07-11 08:50:14 -07:00
|
|
|
`
|
|
|
|
helpers.generateAlert('error', 'Error!', msg)
|
|
|
|
})
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
onChangeFormField(event) {
|
2018-07-11 08:50:14 -07:00
|
|
|
const field = event.target.id
|
|
|
|
const value = event.target.value
|
|
|
|
let form = this.state.form
|
|
|
|
form[field] = value
|
|
|
|
this.setState({ form })
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
render() {
|
2018-07-06 00:05:26 -07:00
|
|
|
if (!this.isValidVotingKey) {
|
2018-07-11 08:56:38 -07:00
|
|
|
return null
|
2018-07-06 00:05:26 -07:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
const BtnAction = this.state.hasData ? 'Update' : 'Set'
|
2017-12-11 17:35:57 -08:00
|
|
|
const AutocompleteItem = ({ formattedSuggestion }) => (
|
|
|
|
<div className="custom-container">
|
2018-07-11 08:50:14 -07:00
|
|
|
<strong>{formattedSuggestion.mainText}</strong> <small>{formattedSuggestion.secondaryText}</small>
|
2017-12-11 17:35:57 -08:00
|
|
|
</div>
|
|
|
|
)
|
2018-01-31 13:24:52 -08:00
|
|
|
|
2017-12-11 17:35:57 -08:00
|
|
|
const inputProps = {
|
|
|
|
value: this.state.form.fullAddress,
|
|
|
|
onChange: this.onChangeAutoComplete,
|
|
|
|
id: 'address'
|
2018-01-31 13:24:52 -08:00
|
|
|
}
|
2018-07-11 08:50:14 -07:00
|
|
|
let loader = this.state.loading ? <Loading /> : ''
|
2018-01-31 13:24:52 -08:00
|
|
|
let createKeyBtn = (
|
|
|
|
<div className="create-keys">
|
|
|
|
<form className="create-keys-form">
|
|
|
|
<div className="create-keys-form-i">
|
|
|
|
<label htmlFor="first-name">First name</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input type="text" id="firstName" value={this.state.form.firstName} onChange={this.onChangeFormField} />
|
2018-01-31 13:24:52 -08:00
|
|
|
<label htmlFor="last-name">Last name</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input type="text" id="lastName" value={this.state.form.lastName} onChange={this.onChangeFormField} />
|
2018-01-31 13:24:52 -08:00
|
|
|
<label htmlFor="address">Address</label>
|
|
|
|
<PlacesAutocomplete onSelect={this.onSelect} inputProps={inputProps} autocompleteItem={AutocompleteItem} />
|
|
|
|
<label htmlFor="state">State</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input type="text" id="us_state" value={this.state.form.us_state} onChange={this.onChangeFormField} />
|
2018-01-31 13:24:52 -08:00
|
|
|
</div>
|
|
|
|
<div className="create-keys-form-i">
|
|
|
|
<label htmlFor="zip">Zip code</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input type="text" id="postal_code" value={this.state.form.postal_code} onChange={this.onChangeFormField} />
|
2018-01-31 13:24:52 -08:00
|
|
|
<label htmlFor="licenseId">License id</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input type="text" id="licenseId" value={this.state.form.licenseId} onChange={this.onChangeFormField} />
|
2018-01-31 13:24:52 -08:00
|
|
|
<label htmlFor="expirationDate">License expiration</label>
|
2018-07-11 08:50:14 -07:00
|
|
|
<input
|
|
|
|
type="date"
|
|
|
|
id="expirationDate"
|
|
|
|
value={this.state.form.expirationDate}
|
|
|
|
onChange={this.onChangeFormField}
|
|
|
|
/>
|
2018-01-31 13:24:52 -08:00
|
|
|
</div>
|
|
|
|
</form>
|
2018-07-11 08:50:14 -07:00
|
|
|
<button onClick={this.onClick} className="create-keys-button">
|
|
|
|
{BtnAction} Metadata
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
let content = createKeyBtn
|
2017-12-11 17:35:57 -08:00
|
|
|
return (
|
|
|
|
<div className="container">
|
|
|
|
{loader}
|
2018-01-31 13:24:52 -08:00
|
|
|
{content}
|
2017-12-11 17:35:57 -08:00
|
|
|
</div>
|
2018-07-11 08:50:14 -07:00
|
|
|
)
|
2017-12-11 17:35:57 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 08:50:14 -07:00
|
|
|
export default App
|