2017-04-21 04:07:09 +02:00
|
|
|
const Component = require('react').Component
|
|
|
|
const h = require('react-hyperscript')
|
|
|
|
const inherits = require('util').inherits
|
|
|
|
const TokenTracker = require('eth-token-tracker')
|
|
|
|
const TokenCell = require('./token-cell.js')
|
2017-06-16 01:22:53 +02:00
|
|
|
const normalizeAddress = require('eth-sig-util').normalize
|
2017-09-05 10:48:52 +02:00
|
|
|
const connect = require('react-redux').connect
|
|
|
|
const selectors = require('../selectors')
|
|
|
|
|
|
|
|
function mapStateToProps (state) {
|
|
|
|
return {
|
|
|
|
network: state.metamask.network,
|
|
|
|
tokens: state.metamask.tokens,
|
|
|
|
userAddress: selectors.getSelectedAddress(state),
|
|
|
|
}
|
|
|
|
}
|
2017-06-14 02:47:56 +02:00
|
|
|
|
2017-06-16 01:22:53 +02:00
|
|
|
const defaultTokens = []
|
2017-06-30 19:21:47 +02:00
|
|
|
const contracts = require('eth-contract-metadata')
|
2017-06-15 00:17:46 +02:00
|
|
|
for (const address in contracts) {
|
2017-06-14 02:47:56 +02:00
|
|
|
const contract = contracts[address]
|
|
|
|
if (contract.erc20) {
|
|
|
|
contract.address = address
|
2017-06-16 01:22:53 +02:00
|
|
|
defaultTokens.push(contract)
|
2017-06-14 02:47:56 +02:00
|
|
|
}
|
|
|
|
}
|
2017-04-21 04:07:09 +02:00
|
|
|
|
2017-09-05 10:48:52 +02:00
|
|
|
module.exports = connect(mapStateToProps)(TokenList)
|
|
|
|
|
2017-04-21 04:07:09 +02:00
|
|
|
|
|
|
|
inherits(TokenList, Component)
|
|
|
|
function TokenList () {
|
2017-06-16 01:22:53 +02:00
|
|
|
this.state = {
|
2017-06-20 17:58:25 +02:00
|
|
|
tokens: [],
|
2017-06-16 01:22:53 +02:00
|
|
|
isLoading: true,
|
|
|
|
network: null,
|
|
|
|
}
|
2017-04-21 04:07:09 +02:00
|
|
|
Component.call(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
TokenList.prototype.render = function () {
|
2017-06-14 02:47:56 +02:00
|
|
|
const state = this.state
|
2017-06-20 04:11:55 +02:00
|
|
|
const { tokens, isLoading, error } = state
|
2017-06-14 02:47:56 +02:00
|
|
|
|
2017-06-15 00:30:03 +02:00
|
|
|
if (isLoading) {
|
2017-09-06 09:33:39 +02:00
|
|
|
return this.message('Loading Tokens...')
|
2017-06-15 00:30:03 +02:00
|
|
|
}
|
2017-06-14 02:47:56 +02:00
|
|
|
|
2017-06-20 04:11:55 +02:00
|
|
|
if (error) {
|
|
|
|
log.error(error)
|
|
|
|
return this.message('There was a problem loading your token balances.')
|
|
|
|
}
|
|
|
|
|
2017-09-06 12:17:49 +02:00
|
|
|
return h('div', tokens.map((tokenData) => h(TokenCell, tokenData)))
|
2017-04-21 04:07:09 +02:00
|
|
|
}
|
|
|
|
|
2017-06-15 03:08:03 +02:00
|
|
|
TokenList.prototype.message = function (body) {
|
|
|
|
return h('div', {
|
|
|
|
style: {
|
|
|
|
display: 'flex',
|
|
|
|
height: '250px',
|
|
|
|
alignItems: 'center',
|
|
|
|
justifyContent: 'center',
|
2017-06-29 01:36:58 +02:00
|
|
|
padding: '30px',
|
2017-06-15 03:08:03 +02:00
|
|
|
},
|
|
|
|
}, body)
|
|
|
|
}
|
|
|
|
|
2017-04-21 04:07:09 +02:00
|
|
|
TokenList.prototype.componentDidMount = function () {
|
2017-06-15 00:17:46 +02:00
|
|
|
this.createFreshTokenTracker()
|
|
|
|
}
|
|
|
|
|
|
|
|
TokenList.prototype.createFreshTokenTracker = function () {
|
|
|
|
if (this.tracker) {
|
2017-06-20 04:11:55 +02:00
|
|
|
// Clean up old trackers when refreshing:
|
2017-06-15 00:17:46 +02:00
|
|
|
this.tracker.stop()
|
2017-06-20 04:11:55 +02:00
|
|
|
this.tracker.removeListener('update', this.balanceUpdater)
|
|
|
|
this.tracker.removeListener('error', this.showError)
|
2017-06-15 00:17:46 +02:00
|
|
|
}
|
|
|
|
|
2017-06-14 02:47:56 +02:00
|
|
|
if (!global.ethereumProvider) return
|
2017-04-21 04:07:09 +02:00
|
|
|
const { userAddress } = this.props
|
2017-09-05 10:48:52 +02:00
|
|
|
|
2017-04-21 04:07:09 +02:00
|
|
|
this.tracker = new TokenTracker({
|
|
|
|
userAddress,
|
2017-06-14 02:47:56 +02:00
|
|
|
provider: global.ethereumProvider,
|
2017-06-16 01:22:53 +02:00
|
|
|
tokens: uniqueMergeTokens(defaultTokens, this.props.tokens),
|
2017-06-14 02:47:56 +02:00
|
|
|
pollingInterval: 8000,
|
2017-04-21 04:07:09 +02:00
|
|
|
})
|
|
|
|
|
2017-06-20 04:11:55 +02:00
|
|
|
|
|
|
|
// Set up listener instances for cleaning up
|
|
|
|
this.balanceUpdater = this.updateBalances.bind(this)
|
|
|
|
this.showError = (error) => {
|
|
|
|
this.setState({ error, isLoading: false })
|
|
|
|
}
|
|
|
|
this.tracker.on('update', this.balanceUpdater)
|
|
|
|
this.tracker.on('error', this.showError)
|
|
|
|
|
2017-04-21 04:07:09 +02:00
|
|
|
this.tracker.updateBalances()
|
2017-06-14 23:21:50 +02:00
|
|
|
.then(() => {
|
|
|
|
this.updateBalances(this.tracker.serialize())
|
|
|
|
})
|
|
|
|
.catch((reason) => {
|
|
|
|
log.error(`Problem updating balances`, reason)
|
|
|
|
this.setState({ isLoading: false })
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-09-06 09:33:39 +02:00
|
|
|
TokenList.prototype.componentDidUpdate = function (nextProps) {
|
|
|
|
const {
|
|
|
|
network: oldNet,
|
|
|
|
userAddress: oldAddress,
|
|
|
|
} = this.props
|
|
|
|
const {
|
|
|
|
network: newNet,
|
|
|
|
userAddress: newAddress,
|
|
|
|
} = nextProps
|
|
|
|
|
|
|
|
if (newNet === 'loading') return
|
|
|
|
if (!oldNet || !newNet || !oldAddress || !newAddress) return
|
|
|
|
if (oldAddress === newAddress && oldNet === newNet) return
|
|
|
|
|
|
|
|
this.setState({ isLoading: true })
|
|
|
|
this.createFreshTokenTracker()
|
2017-06-15 00:17:46 +02:00
|
|
|
}
|
|
|
|
|
2017-06-20 17:58:25 +02:00
|
|
|
TokenList.prototype.updateBalances = function (tokens) {
|
2017-09-06 09:33:39 +02:00
|
|
|
const heldTokens = tokens.filter(token => {
|
|
|
|
return token.balance !== '0' && token.string !== '0.000'
|
|
|
|
})
|
|
|
|
this.setState({ tokens: heldTokens, isLoading: false })
|
2017-04-21 04:07:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
TokenList.prototype.componentWillUnmount = function () {
|
2017-06-14 02:47:56 +02:00
|
|
|
if (!this.tracker) return
|
2017-04-21 04:07:09 +02:00
|
|
|
this.tracker.stop()
|
|
|
|
}
|
2017-06-14 02:47:56 +02:00
|
|
|
|
2017-09-05 10:48:52 +02:00
|
|
|
function uniqueMergeTokens (tokensA, tokensB = []) {
|
2017-06-16 01:22:53 +02:00
|
|
|
const uniqueAddresses = []
|
|
|
|
const result = []
|
|
|
|
tokensA.concat(tokensB).forEach((token) => {
|
|
|
|
const normal = normalizeAddress(token.address)
|
|
|
|
if (!uniqueAddresses.includes(normal)) {
|
|
|
|
uniqueAddresses.push(normal)
|
|
|
|
result.push(token)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|