From c8c48f7da07843355e124347d519d7307d1fbf1a Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 22 Aug 2018 15:32:45 +0300 Subject: [PATCH 1/2] Support of token per network basis --- app/scripts/controllers/detect-tokens.js | 2 +- app/scripts/controllers/preferences.js | 6 +- old-ui/app/add-token.js | 4 +- old-ui/app/components/token-cell.js | 2 - old-ui/app/components/token-list.js | 15 +++-- package-lock.json | 81 +++++++++++++----------- package.json | 2 +- ui/app/actions.js | 12 ++-- ui/app/components/token-balance.js | 2 +- ui/app/components/token-list.js | 2 +- ui/app/helpers/with-token-tracker.js | 2 +- 11 files changed, 71 insertions(+), 59 deletions(-) diff --git a/app/scripts/controllers/detect-tokens.js b/app/scripts/controllers/detect-tokens.js index 195ec918a..098b29b5f 100644 --- a/app/scripts/controllers/detect-tokens.js +++ b/app/scripts/controllers/detect-tokens.js @@ -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) diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index b756808c8..19bc9a746 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -217,13 +217,13 @@ class PreferencesController { * @returns {Promise} 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) diff --git a/old-ui/app/add-token.js b/old-ui/app/add-token.js index 68ebfedfd..325471826 100644 --- a/old-ui/app/add-token.js +++ b/old-ui/app/add-token.js @@ -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()) }) diff --git a/old-ui/app/components/token-cell.js b/old-ui/app/components/token-cell.js index c77858f1c..cb1d0c7fd 100644 --- a/old-ui/app/components/token-cell.js +++ b/old-ui/app/components/token-cell.js @@ -49,8 +49,6 @@ TokenCell.prototype.render = function () { }, }, ''), - h('hr'), - /* h('button', { onClick: this.send.bind(this, address), diff --git a/old-ui/app/components/token-list.js b/old-ui/app/components/token-list.js index 9328c5e1c..77f07e78d 100644 --- a/old-ui/app/components/token-list.js +++ b/old-ui/app/components/token-list.js @@ -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` } diff --git a/package-lock.json b/package-lock.json index 476dc2f82..f80da7918 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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,17 +8993,51 @@ "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": { + "version": "0.1.5", + "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.5", - "resolved": "https://registry.npmjs.org/ethjs-schema/-/ethjs-schema-0.1.5.tgz", - "integrity": "sha1-WXQOOzl3vNu5sRvDBoIB6Kzquw0=" + "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=" } } }, diff --git a/package.json b/package.json index 6ae0eee53..900c00dc2 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/ui/app/actions.js b/ui/app/actions.js index 015bc624c..e5e494d5b 100644 --- a/ui/app/actions.js +++ b/ui/app/actions.js @@ -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)) )) ) } diff --git a/ui/app/components/token-balance.js b/ui/app/components/token-balance.js index 99ca7335c..7498f403c 100644 --- a/ui/app/components/token-balance.js +++ b/ui/app/components/token-balance.js @@ -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') diff --git a/ui/app/components/token-list.js b/ui/app/components/token-list.js index 42351cf89..522fbeaf2 100644 --- a/ui/app/components/token-list.js +++ b/ui/app/components/token-list.js @@ -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') diff --git a/ui/app/helpers/with-token-tracker.js b/ui/app/helpers/with-token-tracker.js index 8608b15f4..a5c5a6b9f 100644 --- a/ui/app/helpers/with-token-tracker.js +++ b/ui/app/helpers/with-token-tracker.js @@ -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 { From 2df903ac69d87faaf68bcc9f79a21f86244cf717 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Wed, 22 Aug 2018 16:18:48 +0300 Subject: [PATCH 2/2] Update changelog and tests --- CHANGELOG.md | 1 + .../unit/app/controllers/detect-tokens-test.js | 18 +++++++++--------- .../controllers/preferences-controller-test.js | 17 ++++++++++------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7731f2449..8d6096bc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/test/unit/app/controllers/detect-tokens-test.js b/test/unit/app/controllers/detect-tokens-test.js index 426ffe23a..282387e30 100644 --- a/test/unit/app/controllers/detect-tokens-test.js +++ b/test/unit/app/controllers/detect-tokens-test.js @@ -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 () => { diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index d06e1a54b..a102d5275 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -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}) }) })