mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-22 17:33:23 +01:00
parent
711a4def86
commit
48789f2a3d
@ -3,6 +3,7 @@
|
|||||||
## Current Master
|
## Current Master
|
||||||
|
|
||||||
- Add list of popular tokens held to the account detail view.
|
- 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.
|
- Add a warning to JSON file import.
|
||||||
|
|
||||||
## 3.7.8 2017-6-12
|
## 3.7.8 2017-6-12
|
||||||
|
@ -8,13 +8,11 @@ class PreferencesController {
|
|||||||
const initState = extend({
|
const initState = extend({
|
||||||
frequentRpcList: [],
|
frequentRpcList: [],
|
||||||
currentAccountTab: 'history',
|
currentAccountTab: 'history',
|
||||||
|
tokens: [],
|
||||||
}, opts.initState)
|
}, opts.initState)
|
||||||
this.store = new ObservableStore(initState)
|
this.store = new ObservableStore(initState)
|
||||||
}
|
}
|
||||||
|
// PUBLIC METHODS
|
||||||
//
|
|
||||||
// PUBLIC METHODS
|
|
||||||
//
|
|
||||||
|
|
||||||
setSelectedAddress (_address) {
|
setSelectedAddress (_address) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -28,6 +26,29 @@ class PreferencesController {
|
|||||||
return this.store.getState().selectedAddress
|
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) {
|
updateFrequentRpcList (_url) {
|
||||||
return this.addToFrequentRpcList(_url)
|
return this.addToFrequentRpcList(_url)
|
||||||
.then((rpcList) => {
|
.then((rpcList) => {
|
||||||
|
@ -275,6 +275,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
|
|
||||||
// PreferencesController
|
// PreferencesController
|
||||||
setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController),
|
setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController),
|
||||||
|
addToken: nodeify(preferencesController.addToken).bind(preferencesController),
|
||||||
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab).bind(preferencesController),
|
setCurrentAccountTab: nodeify(preferencesController.setCurrentAccountTab).bind(preferencesController),
|
||||||
setDefaultRpc: nodeify(this.setDefaultRpc).bind(this),
|
setDefaultRpc: nodeify(this.setDefaultRpc).bind(this),
|
||||||
setCustomRpc: nodeify(this.setCustomRpc).bind(this),
|
setCustomRpc: nodeify(this.setCustomRpc).bind(this),
|
||||||
|
@ -35,6 +35,7 @@ function mapStateToProps (state) {
|
|||||||
conversionRate: state.metamask.conversionRate,
|
conversionRate: state.metamask.conversionRate,
|
||||||
currentCurrency: state.metamask.currentCurrency,
|
currentCurrency: state.metamask.currentCurrency,
|
||||||
currentAccountTab: state.metamask.currentAccountTab,
|
currentAccountTab: state.metamask.currentAccountTab,
|
||||||
|
tokens: state.metamask.tokens,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,13 +274,14 @@ AccountDetailScreen.prototype.tabSections = function () {
|
|||||||
AccountDetailScreen.prototype.tabSwitchView = function () {
|
AccountDetailScreen.prototype.tabSwitchView = function () {
|
||||||
const props = this.props
|
const props = this.props
|
||||||
const { address, network } = props
|
const { address, network } = props
|
||||||
const { currentAccountTab } = this.props
|
const { currentAccountTab, tokens } = this.props
|
||||||
|
|
||||||
switch (currentAccountTab) {
|
switch (currentAccountTab) {
|
||||||
case 'tokens':
|
case 'tokens':
|
||||||
return h(TokenList, {
|
return h(TokenList, {
|
||||||
userAddress: address,
|
userAddress: address,
|
||||||
network,
|
network,
|
||||||
|
tokens,
|
||||||
addToken: () => this.props.dispatch(actions.showAddTokenPage()),
|
addToken: () => this.props.dispatch(actions.showAddTokenPage()),
|
||||||
})
|
})
|
||||||
default:
|
default:
|
||||||
|
@ -124,6 +124,7 @@ var actions = {
|
|||||||
showConfigPage,
|
showConfigPage,
|
||||||
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
|
SHOW_ADD_TOKEN_PAGE: 'SHOW_ADD_TOKEN_PAGE',
|
||||||
showAddTokenPage,
|
showAddTokenPage,
|
||||||
|
addToken,
|
||||||
setRpcTarget: setRpcTarget,
|
setRpcTarget: setRpcTarget,
|
||||||
setDefaultRpcTarget: setDefaultRpcTarget,
|
setDefaultRpcTarget: setDefaultRpcTarget,
|
||||||
setProviderType: setProviderType,
|
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 () {
|
function goBackToInitView () {
|
||||||
return {
|
return {
|
||||||
type: actions.BACK_TO_INIT_MENU,
|
type: actions.BACK_TO_INIT_MENU,
|
||||||
|
@ -30,10 +30,8 @@ function AddTokenScreen () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
AddTokenScreen.prototype.render = function () {
|
AddTokenScreen.prototype.render = function () {
|
||||||
const props = this.props
|
|
||||||
|
|
||||||
const state = this.state
|
const state = this.state
|
||||||
const { warning, address, symbol, decimals } = state
|
const { warning, symbol, decimals } = state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
h('.flex-column.flex-grow', [
|
h('.flex-column.flex-grow', [
|
||||||
@ -138,12 +136,12 @@ AddTokenScreen.prototype.render = function () {
|
|||||||
style: {
|
style: {
|
||||||
alignSelf: 'center',
|
alignSelf: 'center',
|
||||||
},
|
},
|
||||||
onClick (event) {
|
onClick: (event) => {
|
||||||
const valid = this.validateInputs()
|
const valid = this.validateInputs()
|
||||||
if (!valid) return
|
if (!valid) return
|
||||||
|
|
||||||
const { address, symbol, decimals } = state
|
const { address, symbol, decimals } = this.state
|
||||||
this.props.dispatch(addToken(address.trim(), symbol.trim(), decimals))
|
this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
|
||||||
},
|
},
|
||||||
}, 'Add'),
|
}, 'Add'),
|
||||||
]),
|
]),
|
||||||
|
@ -4,13 +4,14 @@ const inherits = require('util').inherits
|
|||||||
const TokenTracker = require('eth-token-tracker')
|
const TokenTracker = require('eth-token-tracker')
|
||||||
const TokenCell = require('./token-cell.js')
|
const TokenCell = require('./token-cell.js')
|
||||||
const contracts = require('eth-contract-metadata')
|
const contracts = require('eth-contract-metadata')
|
||||||
|
const normalizeAddress = require('eth-sig-util').normalize
|
||||||
|
|
||||||
const tokens = []
|
const defaultTokens = []
|
||||||
for (const address in contracts) {
|
for (const address in contracts) {
|
||||||
const contract = contracts[address]
|
const contract = contracts[address]
|
||||||
if (contract.erc20) {
|
if (contract.erc20) {
|
||||||
contract.address = address
|
contract.address = address
|
||||||
tokens.push(contract)
|
defaultTokens.push(contract)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,22 +19,23 @@ module.exports = TokenList
|
|||||||
|
|
||||||
inherits(TokenList, Component)
|
inherits(TokenList, Component)
|
||||||
function TokenList () {
|
function TokenList () {
|
||||||
this.state = { tokens, isLoading: true, network: null }
|
this.state = {
|
||||||
|
tokens: null,
|
||||||
|
isLoading: true,
|
||||||
|
network: null,
|
||||||
|
}
|
||||||
Component.call(this)
|
Component.call(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenList.prototype.render = function () {
|
TokenList.prototype.render = function () {
|
||||||
const state = this.state
|
const state = this.state
|
||||||
const { tokens, isLoading } = state
|
const { isLoading, tokens } = state
|
||||||
|
const { userAddress, network } = this.props
|
||||||
const { userAddress } = this.props
|
|
||||||
|
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
return this.message('Loading')
|
return this.message('Loading')
|
||||||
}
|
}
|
||||||
|
|
||||||
const network = this.props.network
|
|
||||||
|
|
||||||
const tokenViews = tokens.map((tokenData) => {
|
const tokenViews = tokens.map((tokenData) => {
|
||||||
tokenData.network = network
|
tokenData.network = network
|
||||||
tokenData.userAddress = userAddress
|
tokenData.userAddress = userAddress
|
||||||
@ -120,7 +122,7 @@ TokenList.prototype.createFreshTokenTracker = function () {
|
|||||||
this.tracker = new TokenTracker({
|
this.tracker = new TokenTracker({
|
||||||
userAddress,
|
userAddress,
|
||||||
provider: global.ethereumProvider,
|
provider: global.ethereumProvider,
|
||||||
tokens: tokens,
|
tokens: uniqueMergeTokens(defaultTokens, this.props.tokens),
|
||||||
pollingInterval: 8000,
|
pollingInterval: 8000,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -149,7 +151,12 @@ TokenList.prototype.componentWillUpdate = function (nextProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenList.prototype.updateBalances = function (tokenData) {
|
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 })
|
this.setState({ tokens: heldTokens, isLoading: false })
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,3 +165,16 @@ TokenList.prototype.componentWillUnmount = function () {
|
|||||||
this.tracker.stop()
|
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