|
|
@ -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() }) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|