aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app
diff options
context:
space:
mode:
authorDan Finlay <dan@danfinlay.com>2017-06-16 06:38:23 +0800
committerDan Finlay <dan@danfinlay.com>2017-06-16 06:38:23 +0800
commit711a4def86d9e8c626ee554a976d9eab6abdcbee (patch)
tree2846cda91e02fe78a5803ec0282302605a53c0ea /ui/app
parentc4f61768205f325a7592d3158404d56ff13a02d6 (diff)
downloadtangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar.gz
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar.bz2
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar.lz
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar.xz
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.tar.zst
tangerine-wallet-browser-711a4def86d9e8c626ee554a976d9eab6abdcbee.zip
Make add token screen a fully working form
Entering the address of a valid HumanStandardToken even auto-fills the other fields!
Diffstat (limited to 'ui/app')
-rw-r--r--ui/app/add-token.js152
1 files changed, 141 insertions, 11 deletions
diff --git a/ui/app/add-token.js b/ui/app/add-token.js
index cd47709ab..fdbb5fe53 100644
--- a/ui/app/add-token.js
+++ b/ui/app/add-token.js
@@ -4,21 +4,37 @@ const h = require('react-hyperscript')
const connect = require('react-redux').connect
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)
function mapStateToProps (state) {
- return {}
+ return {
+ }
}
inherits(AddTokenScreen, Component)
function AddTokenScreen () {
- this.state = { warning: null }
+ this.state = {
+ warning: null,
+ address: null,
+ symbol: 'TOKEN',
+ decimals: 18,
+ }
Component.call(this)
}
AddTokenScreen.prototype.render = function () {
+ const props = this.props
+
const state = this.state
- const { warning } = state
+ const { warning, address, symbol, decimals } = state
+
return (
h('.flex-column.flex-grow', [
@@ -51,23 +67,69 @@ 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('span', {
+ style: { fontWeight: 'bold', paddingRight: '10px'},
}, 'Token Sybmol'),
]),
h('div', { style: {display: 'flex'} }, [
h('input#token_symbol', {
placeholder: `Like "ETH"`,
+ value: symbol,
style: {
width: 'inherit',
flex: '1 0 auto',
height: '30px',
margin: '8px',
},
- onKeyPress (event) {
- if (event.key === 'Enter') {
- var element = event.target
- var newRpc = element.value
- }
+ onChange: (event) => {
+ var element = event.target
+ var symbol = 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',
},
onClick (event) {
- event.preventDefault()
- var tokenSymbolEl = document.querySelector('input#token_symbol')
- var tokenSymbol = tokenSymbolEl.value
+ const valid = this.validateInputs()
+ if (!valid) return
+
+ const { address, symbol, decimals } = state
+ this.props.dispatch(addToken(address.trim(), symbol.trim(), decimals))
},
}, '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() })
+ }
+}
+