mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 09:23:21 +01:00
parent
711a4def86
commit
48789f2a3d
@ -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
|
||||
//
|
||||
|
||||
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…
Reference in New Issue
Block a user