Make add token screen a fully working form

Entering the address of a valid HumanStandardToken even auto-fills the other fields!
feature/default_network_editable
Dan Finlay 8 years ago
parent c4f6176820
commit 711a4def86
  1. 152
      ui/app/add-token.js

@ -4,21 +4,37 @@ const h = require('react-hyperscript')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const actions = require('./actions') const actions = require('./actions')
const ethUtil = require('ethereumjs-util')
const abi = require('human-standard-token-abi')
const Eth = require('ethjs-query')
const EthContract = require('ethjs-contract')
const emptyAddr = '0x0000000000000000000000000000000000000000'
module.exports = connect(mapStateToProps)(AddTokenScreen) module.exports = connect(mapStateToProps)(AddTokenScreen)
function mapStateToProps (state) { function mapStateToProps (state) {
return {} return {
}
} }
inherits(AddTokenScreen, Component) inherits(AddTokenScreen, Component)
function AddTokenScreen () { function AddTokenScreen () {
this.state = { warning: null } this.state = {
warning: null,
address: null,
symbol: 'TOKEN',
decimals: 18,
}
Component.call(this) Component.call(this)
} }
AddTokenScreen.prototype.render = function () { AddTokenScreen.prototype.render = function () {
const props = this.props
const state = this.state const state = this.state
const { warning } = state const { warning, address, symbol, decimals } = state
return ( return (
h('.flex-column.flex-grow', [ h('.flex-column.flex-grow', [
@ -48,6 +64,26 @@ AddTokenScreen.prototype.render = function () {
}, },
}, [ }, [
h('div', [
h('span', {
style: { fontWeight: 'bold', paddingRight: '10px'},
}, 'Token Address'),
]),
h('section.flex-row.flex-center', [
h('input#token-address', {
name: 'address',
placeholder: 'Token Address',
onChange: this.tokenAddressDidChange.bind(this),
style: {
width: 'inherit',
flex: '1 0 auto',
height: '30px',
margin: '8px',
},
}),
]),
h('div', [ h('div', [
h('span', { h('span', {
style: { fontWeight: 'bold', paddingRight: '10px'}, style: { fontWeight: 'bold', paddingRight: '10px'},
@ -57,17 +93,43 @@ AddTokenScreen.prototype.render = function () {
h('div', { style: {display: 'flex'} }, [ h('div', { style: {display: 'flex'} }, [
h('input#token_symbol', { h('input#token_symbol', {
placeholder: `Like "ETH"`, placeholder: `Like "ETH"`,
value: symbol,
style: { style: {
width: 'inherit', width: 'inherit',
flex: '1 0 auto', flex: '1 0 auto',
height: '30px', height: '30px',
margin: '8px', margin: '8px',
}, },
onKeyPress (event) { onChange: (event) => {
if (event.key === 'Enter') { var element = event.target
var element = event.target var symbol = element.value
var newRpc = element.value this.setState({ symbol })
} },
}),
]),
h('div', [
h('span', {
style: { fontWeight: 'bold', paddingRight: '10px'},
}, 'Decimals of Precision'),
]),
h('div', { style: {display: 'flex'} }, [
h('input#token_decimals', {
value: decimals,
type: 'number',
min: 0,
max: 36,
style: {
width: 'inherit',
flex: '1 0 auto',
height: '30px',
margin: '8px',
},
onChange: (event) => {
var element = event.target
var decimals = element.value.trim()
this.setState({ decimals })
}, },
}), }),
]), ]),
@ -77,9 +139,11 @@ AddTokenScreen.prototype.render = function () {
alignSelf: 'center', alignSelf: 'center',
}, },
onClick (event) { onClick (event) {
event.preventDefault() const valid = this.validateInputs()
var tokenSymbolEl = document.querySelector('input#token_symbol') if (!valid) return
var tokenSymbol = tokenSymbolEl.value
const { address, symbol, decimals } = state
this.props.dispatch(addToken(address.trim(), symbol.trim(), decimals))
}, },
}, 'Add'), }, 'Add'),
]), ]),
@ -88,3 +152,69 @@ AddTokenScreen.prototype.render = function () {
) )
} }
AddTokenScreen.prototype.componentWillMount = function () {
if (typeof global.ethereumProvider === 'undefined') return
this.eth = new Eth(global.ethereumProvider)
this.contract = new EthContract(this.eth)
this.TokenContract = this.contract(abi)
}
AddTokenScreen.prototype.tokenAddressDidChange = function (event) {
const el = event.target
const address = el.value.trim()
if (ethUtil.isValidAddress(address) && address !== emptyAddr) {
this.setState({ address })
this.attemptToAutoFillTokenParams(address)
}
}
AddTokenScreen.prototype.validateInputs = function () {
let msg = ''
const state = this.state
const { address, symbol, decimals } = state
const validAddress = ethUtil.isValidAddress(address)
if (!validAddress) {
msg += 'Address is invalid. '
}
const validDecimals = decimals >= 0 && decimals < 36
if (!validDecimals) {
msg += 'Decimals must be at least 0, and not over 36. '
}
const symbolLen = symbol.trim().length
const validSymbol = symbolLen > 0 && symbolLen < 10
if (!validSymbol) {
msg += 'Symbol must be between 0 and 10 characters.'
}
const isValid = validAddress && validDecimals
if (!isValid) {
this.setState({
warning: msg,
})
} else {
this.setState({ warning: null })
}
return isValid
}
AddTokenScreen.prototype.attemptToAutoFillTokenParams = async function (address) {
const contract = this.TokenContract.at(address)
const results = await Promise.all([
contract.symbol(),
contract.decimals(),
])
const [ symbol, decimals ] = results
if (symbol && decimals) {
console.log('SETTING SYMBOL AND DECIMALS', { symbol, decimals })
this.setState({ symbol: symbol[0], decimals: decimals[0].toString() })
}
}

Loading…
Cancel
Save