Add ability to add tokens to token list

Fiex #1616
feature/default_network_editable
Dan Finlay 7 years ago
parent 711a4def86
commit 48789f2a3d
  1. 1
      CHANGELOG.md
  2. 29
      app/scripts/controllers/preferences.js
  3. 1
      app/scripts/metamask-controller.js
  4. 4
      ui/app/account-detail.js
  5. 14
      ui/app/actions.js
  6. 10
      ui/app/add-token.js
  7. 40
      ui/app/components/token-list.js

@ -3,6 +3,7 @@
## Current Master
- Add list of popular tokens held to the account detail view.
- Add ability to add Tokens to token list.
- Add a warning to JSON file import.
## 3.7.8 2017-6-12

@ -8,13 +8,11 @@ class PreferencesController {
const initState = extend({
frequentRpcList: [],
currentAccountTab: 'history',
tokens: [],
}, opts.initState)
this.store = new ObservableStore(initState)
}
//
// PUBLIC METHODS
//
// PUBLIC METHODS
setSelectedAddress (_address) {
return new Promise((resolve, reject) => {
@ -28,6 +26,29 @@ class PreferencesController {
return this.store.getState().selectedAddress
}
addToken (rawAddress, symbol, decimals) {
const address = normalizeAddress(rawAddress)
const newEntry = { address, symbol, decimals }
const tokens = this.store.getState().tokens
const previousIndex = tokens.find((token, index) => {
return token.address === address
})
if (previousIndex) {
tokens[previousIndex] = newEntry
} else {
tokens.push(newEntry)
}
this.store.updateState({ tokens })
return Promise.resolve()
}
getTokens () {
return this.store.getState().tokens
}
updateFrequentRpcList (_url) {
return this.addToFrequentRpcList(_url)
.then((rpcList) => {

@ -275,6 +275,7 @@ module.exports = class MetamaskController extends EventEmitter {
// PreferencesController
setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController),
addToken: nodeify(preferencesController.addToken).bind(preferencesController),
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab).bind(preferencesController),
setDefaultRpc: nodeify(this.setDefaultRpc).bind(this),
setCustomRpc: nodeify(this.setCustomRpc).bind(this),

@ -35,6 +35,7 @@ function mapStateToProps (state) {
conversionRate: state.metamask.conversionRate,
currentCurrency: state.metamask.currentCurrency,
currentAccountTab: state.metamask.currentAccountTab,
tokens: state.metamask.tokens,
}
}
@ -273,13 +274,14 @@ AccountDetailScreen.prototype.tabSections = function () {
AccountDetailScreen.prototype.tabSwitchView = function () {
const props = this.props
const { address, network } = props
const { currentAccountTab } = this.props
const { currentAccountTab, tokens } = this.props
switch (currentAccountTab) {
case 'tokens':
return h(TokenList, {
userAddress: address,
network,
tokens,
addToken: () => this.props.dispatch(actions.showAddTokenPage()),
})
default:

@ -124,6 +124,7 @@ var actions = {
showConfigPage,
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
showAddTokenPage,
addToken,
setRpcTarget: setRpcTarget,
setDefaultRpcTarget: setDefaultRpcTarget,
setProviderType: setProviderType,
@ -636,6 +637,19 @@ function showAddTokenPage (transitionForward = true) {
}
}
function addToken (address, symbol, decimals) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.addToken(address, symbol, decimals, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.displayWarning(err.message))
}
dispatch(actions.goHome())
})
}
}
function goBackToInitView () {
return {
type: actions.BACK_TO_INIT_MENU,

@ -30,10 +30,8 @@ function AddTokenScreen () {
}
AddTokenScreen.prototype.render = function () {
const props = this.props
const state = this.state
const { warning, address, symbol, decimals } = state
const { warning, symbol, decimals } = state
return (
h('.flex-column.flex-grow', [
@ -138,12 +136,12 @@ AddTokenScreen.prototype.render = function () {
style: {
alignSelf: 'center',
},
onClick (event) {
onClick: (event) => {
const valid = this.validateInputs()
if (!valid) return
const { address, symbol, decimals } = state
this.props.dispatch(addToken(address.trim(), symbol.trim(), decimals))
const { address, symbol, decimals } = this.state
this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
},
}, 'Add'),
]),

@ -4,13 +4,14 @@ const inherits = require('util').inherits
const TokenTracker = require('eth-token-tracker')
const TokenCell = require('./token-cell.js')
const contracts = require('eth-contract-metadata')
const normalizeAddress = require('eth-sig-util').normalize
const tokens = []
const defaultTokens = []
for (const address in contracts) {
const contract = contracts[address]
if (contract.erc20) {
contract.address = address
tokens.push(contract)
defaultTokens.push(contract)
}
}
@ -18,22 +19,23 @@ module.exports = TokenList
inherits(TokenList, Component)
function TokenList () {
this.state = { tokens, isLoading: true, network: null }
this.state = {
tokens: null,
isLoading: true,
network: null,
}
Component.call(this)
}
TokenList.prototype.render = function () {
const state = this.state
const { tokens, isLoading } = state
const { userAddress } = this.props
const { isLoading, tokens } = state
const { userAddress, network } = this.props
if (isLoading) {
return this.message('Loading')
}
const network = this.props.network
const tokenViews = tokens.map((tokenData) => {
tokenData.network = network
tokenData.userAddress = userAddress
@ -120,7 +122,7 @@ TokenList.prototype.createFreshTokenTracker = function () {
this.tracker = new TokenTracker({
userAddress,
provider: global.ethereumProvider,
tokens: tokens,
tokens: uniqueMergeTokens(defaultTokens, this.props.tokens),
pollingInterval: 8000,
})
@ -149,7 +151,12 @@ TokenList.prototype.componentWillUpdate = function (nextProps) {
}
TokenList.prototype.updateBalances = function (tokenData) {
const heldTokens = tokenData.filter(token => token.balance !== '0' && token.string !== '0.000')
const desired = this.props.tokens.map(token => token.address)
const heldTokens = tokenData.filter(token => {
const held = token.balance !== '0' && token.string !== '0.000'
const preferred = desired.includes(normalizeAddress(token.address))
return held || preferred
})
this.setState({ tokens: heldTokens, isLoading: false })
}
@ -158,3 +165,16 @@ TokenList.prototype.componentWillUnmount = function () {
this.tracker.stop()
}
function uniqueMergeTokens (tokensA, tokensB) {
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
}

Loading…
Cancel
Save