Merge pull request #89 from poanetwork/token-per-net
(Feature) Support of token per network basis
This commit is contained in:
commit
6f8a0ab938
|
@ -2,6 +2,7 @@
|
|||
|
||||
## Current Master
|
||||
|
||||
- [#89](https://github.com/poanetwork/metamask-extension/pull/89): (Feature) Support of token per network basis
|
||||
- [#85](https://github.com/poanetwork/metamask-extension/pull/85): (Upgrade) node, npm packages versions
|
||||
- [#84](https://github.com/poanetwork/metamask-extension/pull/84): (Fix) Change green color
|
||||
- [#83](https://github.com/poanetwork/metamask-extension/pull/83): (Feature) Changing of password
|
||||
|
|
|
@ -50,7 +50,7 @@ class DetectTokensController {
|
|||
ethContract.balanceOf(this.selectedAddress, (error, result) => {
|
||||
if (!error) {
|
||||
if (!result.isZero()) {
|
||||
this._preferences.addToken(contractAddress, contracts[contractAddress].symbol, contracts[contractAddress].decimals)
|
||||
this._preferences.addToken(contractAddress, contracts[contractAddress].symbol, contracts[contractAddress].decimals, this.network)
|
||||
}
|
||||
} else {
|
||||
warn(`MetaMask - DetectTokensController balance fetch failed for ${contractAddress}.`, error)
|
||||
|
|
|
@ -217,13 +217,13 @@ class PreferencesController {
|
|||
* @returns {Promise<array>} Promises the new array of AddedToken objects.
|
||||
*
|
||||
*/
|
||||
async addToken (rawAddress, symbol, decimals) {
|
||||
async addToken (rawAddress, symbol, decimals, network) {
|
||||
const address = normalizeAddress(rawAddress)
|
||||
const newEntry = { address, symbol, decimals }
|
||||
const newEntry = { address, symbol, decimals, network }
|
||||
|
||||
const tokens = this.store.getState().tokens
|
||||
const previousEntry = tokens.find((token, index) => {
|
||||
return token.address === address
|
||||
return (token.address === address && parseInt(token.network) === parseInt(network))
|
||||
})
|
||||
const previousIndex = tokens.indexOf(previousEntry)
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ module.exports = connect(mapStateToProps)(AddTokenScreen)
|
|||
function mapStateToProps (state) {
|
||||
return {
|
||||
identities: state.metamask.identities,
|
||||
network: state.metamask.network,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -36,6 +37,7 @@ AddTokenScreen.prototype.render = function () {
|
|||
const state = this.state
|
||||
const props = this.props
|
||||
const { warning, symbol, decimals } = state
|
||||
const { network } = props
|
||||
|
||||
return (
|
||||
h('.flex-column.flex-grow', [
|
||||
|
@ -167,7 +169,7 @@ AddTokenScreen.prototype.render = function () {
|
|||
if (!valid) return
|
||||
|
||||
const { address, symbol, decimals } = this.state
|
||||
this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals))
|
||||
this.props.dispatch(actions.addToken(address.trim(), symbol.trim(), decimals, network))
|
||||
.then(() => {
|
||||
this.props.dispatch(actions.goHome())
|
||||
})
|
||||
|
|
|
@ -49,8 +49,6 @@ TokenCell.prototype.render = function () {
|
|||
},
|
||||
}, ''),
|
||||
|
||||
h('hr'),
|
||||
|
||||
/*
|
||||
h('button', {
|
||||
onClick: this.send.bind(this, address),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const TokenTracker = require('eth-token-tracker')
|
||||
const TokenTracker = require('eth-token-watcher')
|
||||
const TokenCell = require('./token-cell.js')
|
||||
const log = require('loglevel')
|
||||
|
||||
|
@ -48,8 +48,9 @@ TokenList.prototype.render = function () {
|
|||
])
|
||||
}
|
||||
|
||||
const tokenViews = tokens.map((tokenData, ind) => {
|
||||
tokenData.network = network
|
||||
const tokensFromCurrentNetwork = tokens.filter(token => (parseInt(token.network) === parseInt(network) || !token.network))
|
||||
|
||||
const tokenViews = tokensFromCurrentNetwork.map((tokenData, ind) => {
|
||||
tokenData.userAddress = userAddress
|
||||
const isLastTokenCell = ind === (tokens.length - 1)
|
||||
return h(TokenCell, {
|
||||
|
@ -97,12 +98,14 @@ TokenList.prototype.render = function () {
|
|||
|
||||
TokenList.prototype.renderTokenStatusBar = function () {
|
||||
const { tokens } = this.state
|
||||
const { network } = this.props
|
||||
const tokensFromCurrentNetwork = tokens.filter(token => (parseInt(token.network) === parseInt(network) || !token.network))
|
||||
|
||||
let msg
|
||||
if (tokens.length === 1) {
|
||||
if (tokensFromCurrentNetwork.length === 1) {
|
||||
msg = `You own 1 token`
|
||||
} else if (tokens.length > 1) {
|
||||
msg = `You own ${tokens.length} tokens`
|
||||
} else if (tokensFromCurrentNetwork.length > 1) {
|
||||
msg = `You own ${tokensFromCurrentNetwork.length} tokens`
|
||||
} else {
|
||||
msg = `No tokens found`
|
||||
}
|
||||
|
|
|
@ -8863,10 +8863,10 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"eth-token-tracker": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/eth-token-tracker/-/eth-token-tracker-1.1.4.tgz",
|
||||
"integrity": "sha1-Kf8kV9Zr+juO5JDoP/QP0M8s7EE=",
|
||||
"eth-token-watcher": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/eth-token-watcher/-/eth-token-watcher-1.1.5.tgz",
|
||||
"integrity": "sha512-7cHDwFtSXpHonTRNDmY8a7yzLnoRQG9VJIllczE+L/NzBW6qc0m+cJcQjgFYiXvwtyFwyf8eaYseawTSOe7Efg==",
|
||||
"requires": {
|
||||
"deep-equal": "^1.0.1",
|
||||
"eth-block-tracker": "^1.0.7",
|
||||
|
@ -8901,13 +8901,6 @@
|
|||
"ethjs-util": "^0.1.3",
|
||||
"pify": "^2.3.0",
|
||||
"tape": "^4.6.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ethjs": {
|
||||
|
@ -8927,19 +8920,6 @@
|
|||
"number-to-bn": "1.7.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethjs-format": {
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-format/-/ethjs-format-0.2.3.tgz",
|
||||
"integrity": "sha1-m9hnyu6CstvtmEYAuzAiDPPLWDA=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.6",
|
||||
"ethjs-schema": "^0.1.6",
|
||||
"ethjs-util": "0.1.3",
|
||||
"is-hex-prefixed": "1.0.0",
|
||||
"number-to-bn": "1.7.0",
|
||||
"strip-hex-prefix": "1.0.0"
|
||||
}
|
||||
},
|
||||
"ethjs-query": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-query/-/ethjs-query-0.3.0.tgz",
|
||||
|
@ -8949,11 +8929,6 @@
|
|||
"ethjs-rpc": "0.1.5"
|
||||
}
|
||||
},
|
||||
"ethjs-schema": {
|
||||
"version": "0.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-schema/-/ethjs-schema-0.1.9.tgz",
|
||||
"integrity": "sha1-hYwqXacGrgSBK0zosetLSSHjMJI="
|
||||
},
|
||||
"ethjs-util": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.3.tgz",
|
||||
|
@ -8988,12 +8963,12 @@
|
|||
}
|
||||
},
|
||||
"ethjs-format": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-format/-/ethjs-format-0.2.2.tgz",
|
||||
"integrity": "sha1-1zs6YFwuElcHn3B3/VRI6ZjOD80=",
|
||||
"version": "0.2.3",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-format/-/ethjs-format-0.2.3.tgz",
|
||||
"integrity": "sha1-m9hnyu6CstvtmEYAuzAiDPPLWDA=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.6",
|
||||
"ethjs-schema": "0.1.5",
|
||||
"ethjs-schema": "^0.1.6",
|
||||
"ethjs-util": "0.1.3",
|
||||
"is-hex-prefixed": "1.0.0",
|
||||
"number-to-bn": "1.7.0",
|
||||
|
@ -9018,6 +8993,19 @@
|
|||
"requires": {
|
||||
"ethjs-format": "0.2.2",
|
||||
"ethjs-rpc": "0.1.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ethjs-format": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-format/-/ethjs-format-0.2.2.tgz",
|
||||
"integrity": "sha1-1zs6YFwuElcHn3B3/VRI6ZjOD80=",
|
||||
"requires": {
|
||||
"bn.js": "4.11.6",
|
||||
"ethjs-schema": "0.1.5",
|
||||
"ethjs-util": "0.1.3",
|
||||
"is-hex-prefixed": "1.0.0",
|
||||
"number-to-bn": "1.7.0",
|
||||
"strip-hex-prefix": "1.0.0"
|
||||
}
|
||||
},
|
||||
"ethjs-schema": {
|
||||
|
@ -9025,10 +9013,31 @@
|
|||
"resolved": "https://registry.npmjs.org/ethjs-schema/-/ethjs-schema-0.1.5.tgz",
|
||||
"integrity": "sha1-WXQOOzl3vNu5sRvDBoIB6Kzquw0="
|
||||
},
|
||||
"ethjs-util": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.3.tgz",
|
||||
"integrity": "sha1-39XqSkANxeQhqInK9H4IGtp4u1U=",
|
||||
"requires": {
|
||||
"is-hex-prefixed": "1.0.0",
|
||||
"strip-hex-prefix": "1.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"ethjs-schema": {
|
||||
"version": "0.1.9",
|
||||
"resolved": "https://registry.npmjs.org/ethjs-schema/-/ethjs-schema-0.1.9.tgz",
|
||||
"integrity": "sha1-hYwqXacGrgSBK0zosetLSSHjMJI="
|
||||
},
|
||||
"js-sha3": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.5.tgz",
|
||||
"integrity": "sha1-uvDA6MVK1ZA0R9+Wreekobynmko="
|
||||
},
|
||||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -113,7 +113,7 @@
|
|||
"eth-phishing-detect": "^1.1.4",
|
||||
"eth-query": "^2.1.2",
|
||||
"eth-sig-util": "^1.4.2",
|
||||
"eth-token-tracker": "^1.1.4",
|
||||
"eth-token-watcher": "^1.1.5",
|
||||
"eth-trezor-keyring": "^0.1.0",
|
||||
"ethereumjs-abi": "^0.6.4",
|
||||
"ethereumjs-tx": "^1.3.0",
|
||||
|
|
|
@ -70,33 +70,33 @@ describe('DetectTokensController', () => {
|
|||
|
||||
sandbox.stub(controller, 'detectTokenBalance')
|
||||
.withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4')
|
||||
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8))
|
||||
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8, 1))
|
||||
.withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388')
|
||||
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18))
|
||||
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18, 1))
|
||||
|
||||
await controller.detectNewTokens()
|
||||
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'},
|
||||
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}])
|
||||
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T', network: 1},
|
||||
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK', network: 1}])
|
||||
})
|
||||
|
||||
it('should not detect same token while in main network', async () => {
|
||||
const network = new NetworkController()
|
||||
network.setProviderType('mainnet')
|
||||
const preferences = new PreferencesController()
|
||||
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8)
|
||||
preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8, 1)
|
||||
const controller = new DetectTokensController({ preferences: preferences, network: network, keyringMemStore: keyringMemStore })
|
||||
controller.isOpen = true
|
||||
controller.isUnlocked = true
|
||||
|
||||
sandbox.stub(controller, 'detectTokenBalance')
|
||||
.withArgs('0x0D262e5dC4A06a0F1c90cE79C7a60C09DfC884E4')
|
||||
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8))
|
||||
.returns(preferences.addToken('0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', 'J8T', 8, 1))
|
||||
.withArgs('0xBC86727E770de68B1060C91f6BB6945c73e10388')
|
||||
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18))
|
||||
.returns(preferences.addToken('0xbc86727e770de68b1060c91f6bb6945c73e10388', 'XNK', 18, 1))
|
||||
|
||||
await controller.detectNewTokens()
|
||||
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T'},
|
||||
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK'}])
|
||||
assert.deepEqual(preferences.store.getState().tokens, [{address: '0x0d262e5dc4a06a0f1c90ce79c7a60c09dfc884e4', decimals: 8, symbol: 'J8T', network: 1},
|
||||
{address: '0xbc86727e770de68b1060c91f6bb6945c73e10388', decimals: 18, symbol: 'XNK', network: 1}])
|
||||
})
|
||||
|
||||
it('should trigger detect new tokens when change address', async () => {
|
||||
|
|
|
@ -129,12 +129,13 @@ describe('preferences controller', function () {
|
|||
const address = '0xabcdef1234567'
|
||||
const symbol = 'ABBR'
|
||||
const decimals = 5
|
||||
const network = 1
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
await preferencesController.addToken(address, symbol, decimals, network)
|
||||
|
||||
const newDecimals = 6
|
||||
await preferencesController.addToken(address, symbol, newDecimals)
|
||||
await preferencesController.addToken(address, symbol, newDecimals, network)
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
assert.equal(tokens.length, 1, 'one token added')
|
||||
|
@ -143,19 +144,21 @@ describe('preferences controller', function () {
|
|||
assert.equal(added.address, address, 'set address correctly')
|
||||
assert.equal(added.symbol, symbol, 'set symbol correctly')
|
||||
assert.equal(added.decimals, newDecimals, 'updated decimals correctly')
|
||||
assert.equal(added.network, network, 'set network correctly')
|
||||
})
|
||||
|
||||
it('should allow adding tokens to two separate addresses', async function () {
|
||||
const address = '0xabcdef1234567'
|
||||
const symbol = 'ABBR'
|
||||
const decimals = 5
|
||||
const network = 1
|
||||
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
await preferencesController.addToken(address, symbol, decimals, network)
|
||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 1st address')
|
||||
|
||||
await preferencesController.setSelectedAddress('0xda22le')
|
||||
await preferencesController.addToken(address, symbol, decimals)
|
||||
await preferencesController.addToken(address, symbol, decimals, network)
|
||||
assert.equal(preferencesController.getTokens().length, 1, 'one token added for 2nd address')
|
||||
})
|
||||
})
|
||||
|
@ -172,15 +175,15 @@ describe('preferences controller', function () {
|
|||
|
||||
it('should remove a token from its state', async function () {
|
||||
await preferencesController.setSelectedAddress('0x7e57e2')
|
||||
await preferencesController.addToken('0xa', 'A', 4)
|
||||
await preferencesController.addToken('0xb', 'B', 5)
|
||||
await preferencesController.addToken('0xa', 'A', 4, 1)
|
||||
await preferencesController.addToken('0xb', 'B', 5, 1)
|
||||
await preferencesController.removeToken('0xa')
|
||||
|
||||
const tokens = preferencesController.getTokens()
|
||||
assert.equal(tokens.length, 1, 'one token removed')
|
||||
|
||||
const [token1] = tokens
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5})
|
||||
assert.deepEqual(token1, {address: '0xb', symbol: 'B', decimals: 5, network: 1})
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1596,11 +1596,11 @@ function showRemoveTokenPage (token, transitionForward = true) {
|
|||
}
|
||||
}
|
||||
|
||||
function addToken (address, symbol, decimals) {
|
||||
function addToken (address, symbol, decimals, network) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
return new Promise((resolve, reject) => {
|
||||
background.addToken(address, symbol, decimals, (err, tokens) => {
|
||||
background.addToken(address, symbol, decimals, network, (err, tokens) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
dispatch(actions.displayWarning(err.message))
|
||||
|
@ -1634,16 +1634,16 @@ function addTokens (tokens) {
|
|||
return dispatch => {
|
||||
if (Array.isArray(tokens)) {
|
||||
dispatch(actions.setSelectedToken(getTokenAddressFromTokenObject(tokens[0])))
|
||||
return Promise.all(tokens.map(({ address, symbol, decimals }) => (
|
||||
dispatch(addToken(address, symbol, decimals))
|
||||
return Promise.all(tokens.map(({ address, symbol, decimals, network }) => (
|
||||
dispatch(addToken(address, symbol, decimals, network))
|
||||
)))
|
||||
} else {
|
||||
dispatch(actions.setSelectedToken(getTokenAddressFromTokenObject(tokens)))
|
||||
return Promise.all(
|
||||
Object
|
||||
.entries(tokens)
|
||||
.map(([_, { address, symbol, decimals }]) => (
|
||||
dispatch(addToken(address, symbol, decimals))
|
||||
.map(([_, { address, symbol, decimals, network }]) => (
|
||||
dispatch(addToken(address, symbol, decimals, network))
|
||||
))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const Component = require('react').Component
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const TokenTracker = require('eth-token-tracker')
|
||||
const TokenTracker = require('eth-token-watcher')
|
||||
const connect = require('react-redux').connect
|
||||
const selectors = require('../selectors')
|
||||
const log = require('loglevel')
|
||||
|
|
|
@ -2,7 +2,7 @@ const Component = require('react').Component
|
|||
const PropTypes = require('prop-types')
|
||||
const h = require('react-hyperscript')
|
||||
const inherits = require('util').inherits
|
||||
const TokenTracker = require('eth-token-tracker')
|
||||
const TokenTracker = require('eth-token-watcher')
|
||||
const TokenCell = require('./token-cell.js')
|
||||
const connect = require('react-redux').connect
|
||||
const selectors = require('../selectors')
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import TokenTracker from 'eth-token-tracker'
|
||||
import TokenTracker from 'eth-token-watcher'
|
||||
|
||||
const withTokenTracker = WrappedComponent => {
|
||||
return class TokenTrackerWrappedComponent extends Component {
|
||||
|
|
Loading…
Reference in New Issue