diff --git a/.circleci/config.yml b/.circleci/config.yml index 64aaa2674..20765d1a9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -96,7 +96,7 @@ workflows: jobs: prep-deps-npm: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -104,14 +104,14 @@ jobs: - run: name: Install npm 6 + deps via npm command: | - sudo npm install -g npm@6.1.0 && npm install --no-save + sudo npm install -g npm@6.4.1 && npm install --no-save - save_cache: key: dependency-cache-{{ .Revision }} paths: - node_modules prep-deps-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -126,7 +126,7 @@ jobs: prep-build: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -145,7 +145,7 @@ jobs: prep-docs: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -160,7 +160,7 @@ jobs: prep-scss: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -179,7 +179,7 @@ jobs: test-lint: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -190,7 +190,7 @@ jobs: test-deps: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -201,7 +201,7 @@ jobs: test-e2e-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -217,7 +217,7 @@ jobs: test-e2e-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -238,7 +238,7 @@ jobs: test-e2e-beta-chrome: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -254,7 +254,7 @@ jobs: test-e2e-beta-firefox: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -275,7 +275,7 @@ jobs: job-screens: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -292,7 +292,7 @@ jobs: job-publish-prerelease: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -319,7 +319,7 @@ jobs: job-publish-release: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -332,7 +332,7 @@ jobs: job-publish-postrelease: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -355,7 +355,7 @@ jobs: test-unit: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -368,7 +368,7 @@ jobs: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -392,7 +392,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -411,7 +411,7 @@ jobs: environment: browsers: '["Firefox"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -435,7 +435,7 @@ jobs: environment: browsers: '["Chrome"]' docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - checkout - restore_cache: @@ -452,7 +452,7 @@ jobs: all-tests-pass: docker: - - image: circleci/node:8.11.4-browsers + - image: circleci/node:8.12.0-browsers steps: - run: name: All Tests Passed diff --git a/.nvmrc b/.nvmrc index 08df4d99f..368fe859d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v8.11.4 +v8.12.0 diff --git a/gulpfile.js b/gulpfile.js index 480f544d8..433257a68 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -70,6 +70,10 @@ createCopyTasks('contractImages', { source: './node_modules/eth-contract-metadata/images/', destinations: commonPlatforms.map(platform => `./dist/${platform}/images/contract`), }) +createCopyTasks('contractImagesPOA', { + source: './node_modules/poa-contract-metadata/images/', + destinations: commonPlatforms.map(platform => `./dist/${platform}/images/contractPOA`), +}) createCopyTasks('fonts', { source: './app/fonts/', destinations: commonPlatforms.map(platform => `./dist/${platform}/fonts`), diff --git a/old-ui/app/components/add-token/add-token.component.js b/old-ui/app/components/add-token/add-token.component.js index 59494c090..f57c558c3 100644 --- a/old-ui/app/components/add-token/add-token.component.js +++ b/old-ui/app/components/add-token/add-token.component.js @@ -3,7 +3,7 @@ const { Component } = React const h = require('react-hyperscript') const Tooltip = require('../tooltip.js') const TabBar = require('../tab-bar') -const { checkExistingAddresses } = require('../../../../ui/app/components/pages/add-token/util') +const { checkExistingAddresses } = require('./util') const TokenList = require('./token-list') const TokenSearch = require('./token-search') const { tokenInfoGetter } = require('../../../../ui/app/token-util') @@ -24,6 +24,7 @@ class AddTokenScreen extends Component { } static propTypes = { + goHome: PropTypes.func, setPendingTokens: PropTypes.func, pendingTokens: PropTypes.object, clearPendingTokens: PropTypes.func, @@ -90,7 +91,8 @@ class AddTokenScreen extends Component { const { network } = this.props const networkID = parseInt(network) let views = [] - networkID === 1 ? views = [h(TabBar, { + const isProdNetwork = networkID === 1 || networkID === 99 + isProdNetwork ? views = [h(TabBar, { style: { paddingTop: '0px', }, @@ -258,15 +260,14 @@ class AddTokenScreen extends Component { } renderTabBar () { - const props = this.props - const state = this.state - const { tokenSelectorError, selectedTokens, searchResults } = state - const { clearPendingTokens, goHome } = props + const { tokenSelectorError, selectedTokens, searchResults } = this.state + const { clearPendingTokens, goHome, network } = this.props return h('div', [ h('.add-token__search-token', [ h(TokenSearch, { onSearch: ({ results = [] }) => this.setState({ searchResults: results }), error: tokenSelectorError, + network: network, }), h('.add-token__token-list', { style: { @@ -278,6 +279,7 @@ class AddTokenScreen extends Component { h(TokenList, { results: searchResults, selectedTokens: selectedTokens, + network: network, onToggleToken: token => this.handleToggleToken(token), }), ]), @@ -312,6 +314,22 @@ class AddTokenScreen extends Component { displayWarning('') } + componentWillUpdate (nextProps) { + const { + network: oldNet, + } = this.props + const { + network: newNet, + } = nextProps + + if (oldNet !== newNet) { + this.setState({ + selectedTokens: {}, + searchResults: [], + }) + } + } + validateInputs () { let msg = '' const state = this.state diff --git a/old-ui/app/components/add-token/token-list/token-list.component.js b/old-ui/app/components/add-token/token-list/token-list.component.js index a4857ebe0..a93992c75 100644 --- a/old-ui/app/components/add-token/token-list/token-list.component.js +++ b/old-ui/app/components/add-token/token-list/token-list.component.js @@ -11,6 +11,7 @@ export default class InfoBox extends Component { } static propTypes = { + network: PropTypes.string, tokens: PropTypes.array, results: PropTypes.array, selectedTokens: PropTypes.object, @@ -18,7 +19,9 @@ export default class InfoBox extends Component { } render () { - const { results = [], selectedTokens = {}, onToggleToken, tokens = [] } = this.props + const { results = [], selectedTokens = {}, onToggleToken, tokens = [], network } = this.props + const networkID = parseInt(network) + const imagesFolder = networkID === 1 ? 'images/contract' : 'images/contractPOA' return results.length === 0 ? @@ -43,7 +46,7 @@ export default class InfoBox extends Component {
diff --git a/old-ui/app/components/add-token/token-search/index.js b/old-ui/app/components/add-token/token-search/index.js index acaa6b084..c3f7524c6 100644 --- a/old-ui/app/components/add-token/token-search/index.js +++ b/old-ui/app/components/add-token/token-search/index.js @@ -1,2 +1,2 @@ -import TokenSearch from './token-search.component' +import TokenSearch from './token-search.container' module.exports = TokenSearch diff --git a/old-ui/app/components/add-token/token-search/token-search.component.js b/old-ui/app/components/add-token/token-search/token-search.component.js index ccba57173..5cea38742 100644 --- a/old-ui/app/components/add-token/token-search/token-search.component.js +++ b/old-ui/app/components/add-token/token-search/token-search.component.js @@ -1,26 +1,14 @@ import React, { Component } from 'react' import PropTypes from 'prop-types' -import contractMap from 'eth-contract-metadata' +import contractMapETH from 'eth-contract-metadata' +import contractMapPOA from 'poa-contract-metadata' import Fuse from 'fuse.js' import InputAdornment from '@material-ui/core/InputAdornment' import TextField from '../../../../../ui/app/components/text-field' -const contractList = Object.entries(contractMap) - .map(([ _, tokenData]) => tokenData) - .filter(tokenData => Boolean(tokenData.erc20)) +let contractList -const fuse = new Fuse(contractList, { - shouldSort: true, - threshold: 0.45, - location: 0, - distance: 100, - maxPatternLength: 32, - minMatchCharLength: 1, - keys: [ - { name: 'name', weight: 0.5 }, - { name: 'symbol', weight: 0.5 }, - ], -}) +let fuse export default class TokenSearch extends Component { static contextTypes = { @@ -32,6 +20,7 @@ export default class TokenSearch extends Component { } static propTypes = { + network: PropTypes.string, onSearch: PropTypes.func, error: PropTypes.string, } @@ -42,6 +31,9 @@ export default class TokenSearch extends Component { this.state = { searchQuery: '', } + + const networkID = parseInt(props.network) + this.updateContractList(networkID) } handleSearch (searchQuery) { @@ -54,6 +46,42 @@ export default class TokenSearch extends Component { this.props.onSearch({ searchQuery, results }) } + componentWillUpdate (nextProps) { + const { + network: oldNet, + } = this.props + const { + network: newNet, + } = nextProps + + if (oldNet !== newNet) { + const newNetworkID = parseInt(newNet) + this.updateContractList(newNetworkID) + this.setState({ searchQuery: '' }) + this.props.onSearch({ searchQuery: '', results: [] }) + } + } + + updateContractList (newNetworkID) { + const contractMap = newNetworkID === 1 ? contractMapETH : contractMapPOA + contractList = Object.entries(contractMap) + .map(([ _, tokenData]) => tokenData) + .filter(tokenData => Boolean(tokenData.erc20)) + + fuse = new Fuse(contractList, { + shouldSort: true, + threshold: 0.45, + location: 0, + distance: 100, + maxPatternLength: 32, + minMatchCharLength: 1, + keys: [ + { name: 'name', weight: 0.5 }, + { name: 'symbol', weight: 0.5 }, + ], + }) + } + renderAdornment () { return ( { + const { network } = metamask + return { + network, + } +} + +const mapDispatchToProps = dispatch => { + return { + clearPendingTokens: () => dispatch(clearPendingTokens()), + } +} + + +export default connect(mapStateToProps, mapDispatchToProps)(TokenSearch) diff --git a/old-ui/app/components/confirm-add-token/confirm-add-token.component.js b/old-ui/app/components/confirm-add-token/confirm-add-token.component.js index 0e4de2392..704abadf2 100644 --- a/old-ui/app/components/confirm-add-token/confirm-add-token.component.js +++ b/old-ui/app/components/confirm-add-token/confirm-add-token.component.js @@ -10,6 +10,7 @@ export default class ConfirmAddToken extends Component { } static propTypes = { + network: PropTypes.string, clearPendingTokens: PropTypes.func, addTokens: PropTypes.func, pendingTokens: PropTypes.object, @@ -31,9 +32,25 @@ export default class ConfirmAddToken extends Component { : `${name} (${symbol})` } + componentWillUpdate (nextProps) { + const { clearPendingTokens, showAddTokenPage } = this.props + const { + network: oldNet, + } = this.props + const { + network: newNet, + } = nextProps + + if (oldNet !== newNet) { + clearPendingTokens() + showAddTokenPage() + } + } + render () { - const { addTokens, clearPendingTokens, pendingTokens, goHome, showAddTokenPage } = this.props + const { addTokens, clearPendingTokens, pendingTokens, goHome, showAddTokenPage, network } = this.props const areMultipleTokens = pendingTokens && Object.keys(pendingTokens).length > 1 + const likeToAddTokensText = areMultipleTokens ? 'Would you like to add these tokens?' : 'Would you like to add this token?' return (
@@ -42,7 +59,7 @@ export default class ConfirmAddToken extends Component { { 'Add Tokens' /* this.context.t('addTokens')*/ }

- { areMultipleTokens ? 'Would you like to add these tokens?' : 'Would you like to add this token?' /* this.context.t('likeToAddTokens')*/ } + { likeToAddTokensText /* this.context.t('likeToAddTokens')*/ }

@@ -71,6 +88,7 @@ export default class ConfirmAddToken extends Component { className="confirm-add-token__token-icon" diameter={48} address={address} + network={network} />
{ this.getTokenName(name, symbol) } diff --git a/old-ui/app/components/confirm-add-token/confirm-add-token.container.js b/old-ui/app/components/confirm-add-token/confirm-add-token.container.js index 11462e948..dc1d8bbba 100644 --- a/old-ui/app/components/confirm-add-token/confirm-add-token.container.js +++ b/old-ui/app/components/confirm-add-token/confirm-add-token.container.js @@ -4,9 +4,10 @@ import ConfirmAddToken from './confirm-add-token.component' const { addTokens, clearPendingTokens, goHome, showAddTokenPage } = require('../../../../ui/app/actions') const mapStateToProps = ({ metamask }) => { - const { pendingTokens } = metamask + const { pendingTokens, network } = metamask return { pendingTokens, + network, } } diff --git a/old-ui/app/components/identicon.js b/old-ui/app/components/identicon.js index cb7376147..54a7b698e 100644 --- a/old-ui/app/components/identicon.js +++ b/old-ui/app/components/identicon.js @@ -37,7 +37,7 @@ IdenticonComponent.prototype.render = function () { IdenticonComponent.prototype.componentDidMount = function () { var props = this.props - const { address } = props + const { address, network } = props if (!address) return @@ -46,14 +46,14 @@ IdenticonComponent.prototype.componentDidMount = function () { var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) + var img = iconFactory.iconForAddress(address, diameter, network) container.appendChild(img) } } IdenticonComponent.prototype.componentDidUpdate = function () { var props = this.props - const { address } = props + const { address, network } = props if (!address) return @@ -67,7 +67,7 @@ IdenticonComponent.prototype.componentDidUpdate = function () { var diameter = props.diameter || this.defaultDiameter if (!isNode) { - var img = iconFactory.iconForAddress(address, diameter) + var img = iconFactory.iconForAddress(address, diameter, network) container.appendChild(img) } } diff --git a/old-ui/app/components/token-list.js b/old-ui/app/components/token-list.js index 9ee1c6e70..30a902ca2 100644 --- a/old-ui/app/components/token-list.js +++ b/old-ui/app/components/token-list.js @@ -3,9 +3,38 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const TokenTracker = require('eth-token-watcher') const TokenCell = require('./token-cell.js') +const connect = require('react-redux').connect +const selectors = require('../../../ui/app/selectors') const log = require('loglevel') -module.exports = TokenList +function mapStateToProps (state) { + return { + network: state.metamask.network, + tokens: state.metamask.tokens, + userAddress: selectors.getSelectedAddress(state), + } +} + +const defaultTokens = [] + +const contractsETH = require('eth-contract-metadata') +const contractsPOA = require('poa-contract-metadata') +for (const address in contractsETH) { + const contract = contractsETH[address] + if (contract.erc20) { + contract.address = address + defaultTokens.push(contract) + } +} +for (const address in contractsPOA) { + const contract = contractsPOA[address] + if (contract.erc20) { + contract.address = address + defaultTokens.push(contract) + } +} + +module.exports = connect(mapStateToProps)(TokenList) inherits(TokenList, Component) function TokenList () { @@ -153,7 +182,7 @@ TokenList.prototype.componentDidMount = function () { this.createFreshTokenTracker() } -TokenList.prototype.createFreshTokenTracker = function (userAddress) { +TokenList.prototype.createFreshTokenTracker = function () { if (this.tracker) { // Clean up old trackers when refreshing: this.tracker.stop() @@ -162,8 +191,10 @@ TokenList.prototype.createFreshTokenTracker = function (userAddress) { } if (!global.ethereumProvider) return + const { userAddress } = this.props + this.tracker = new TokenTracker({ - userAddress: userAddress || this.props.userAddress, + userAddress, provider: global.ethereumProvider, tokens: this.props.tokens, pollingInterval: 8000, @@ -188,26 +219,42 @@ TokenList.prototype.createFreshTokenTracker = function (userAddress) { }) } -TokenList.prototype.componentWillUpdate = function (nextProps) { - if (nextProps.network === 'loading') return - const oldNet = this.props.network - const newNet = nextProps.network +TokenList.prototype.componentDidUpdate = function (nextProps) { + const { + network: oldNet, + userAddress: oldAddress, + tokens, + } = this.props + const { + network: newNet, + userAddress: newAddress, + tokens: newTokens, + } = nextProps - const oldAddress = this.props.userAddress - const newAddress = nextProps.userAddress + const isLoading = newNet === 'loading' + const missingInfo = !oldNet || !newNet || !oldAddress || !newAddress + const sameUserAndNetwork = oldAddress === newAddress && oldNet === newNet + const shouldUpdateTokens = isLoading || missingInfo || sameUserAndNetwork - if (oldNet && newNet && (newNet !== oldNet || newAddress !== oldAddress)) { - this.setState({ isLoading: true }) - this.createFreshTokenTracker(newAddress) - } + const oldTokensLength = tokens ? tokens.length : 0 + const tokensLengthUnchanged = oldTokensLength === newTokens.length + + if (tokensLengthUnchanged && shouldUpdateTokens) return + + this.setState({ isLoading: true }) + this.createFreshTokenTracker() } TokenList.prototype.updateBalances = function (tokens) { - this.setState({ tokens, error: null, isLoading: false }) + if (!this.tracker.running) { + return + } + this.setState({ tokens, isLoading: false }) } TokenList.prototype.componentWillUnmount = function () { if (!this.tracker) return this.tracker.stop() + this.tracker.removeListener('update', this.balanceUpdater) + this.tracker.removeListener('error', this.showError) } - diff --git a/old-ui/lib/icon-factory.js b/old-ui/lib/icon-factory.js index 12533ca44..ecebc8b03 100644 --- a/old-ui/lib/icon-factory.js +++ b/old-ui/lib/icon-factory.js @@ -1,26 +1,28 @@ var iconFactory const isValidAddress = require('ethereumjs-util').isValidAddress const toChecksumAddress = require('ethereumjs-util').toChecksumAddress -const contractMap = require('eth-contract-metadata') +const contractMapETH = require('eth-contract-metadata') +const contractMapPOA = require('poa-contract-metadata') const colors = require('../../colors') -module.exports = function (jazzicon) { +module.exports = function (rockicon) { if (!iconFactory) { - iconFactory = new IconFactory(jazzicon) + iconFactory = new IconFactory(rockicon) } return iconFactory } -function IconFactory (jazzicon) { - jazzicon.setColorsPalette(colors) - this.jazzicon = jazzicon +function IconFactory (rockicon) { + rockicon.setColorsPalette(colors) + this.rockicon = rockicon this.cache = {} } -IconFactory.prototype.iconForAddress = function (address, diameter) { +IconFactory.prototype.iconForAddress = function (address, diameter, network) { + const networkID = parseInt(network) const addr = toChecksumAddress(address) - if (iconExistsFor(addr)) { - return imageElFor(addr) + if (iconExistsFor(addr, networkID)) { + return imageElFor(addr, networkID) } return this.generateIdenticonSvg(address, diameter) @@ -39,20 +41,24 @@ IconFactory.prototype.generateIdenticonSvg = function (address, diameter) { // creates a new identicon IconFactory.prototype.generateNewIdenticon = function (address, diameter) { var numericRepresentation = jsNumberForAddress(address) - var identicon = this.jazzicon.generateIdenticon(diameter, numericRepresentation) + var identicon = this.rockicon.generateIdenticon(diameter, numericRepresentation) return identicon } // util -function iconExistsFor (address) { +function iconExistsFor (address, networkID) { + const contractMap = networkID === 1 ? contractMapETH : contractMapPOA return contractMap[address] && isValidAddress(address) && contractMap[address].logo } -function imageElFor (address) { +function imageElFor (address, networkID) { + const contractMap = networkID === 1 ? contractMapETH : contractMapPOA + console.log(contractMap) const contract = contractMap[address] const fileName = contract.logo - const path = `images/contract/${fileName}` + const imagesFolder = networkID === 1 ? 'images/contract' : 'images/contractPOA' + const path = `${imagesFolder}/${fileName}` const img = document.createElement('img') img.src = path img.style.width = '75%' diff --git a/package-lock.json b/package-lock.json index 830aff1a2..3588fbb20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23820,6 +23820,10 @@ "integrity": "sha1-HMfCEjA6yr50Jj7DrHgAlYAkLZM=", "dev": true }, + "poa-contract-metadata": { + "version": "github:poanetwork/poa-contract-metadata#daee2eab58db1cb2aad50cd58c45374f614f029e", + "from": "github:poanetwork/poa-contract-metadata#master" + }, "pojo-migrator": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/pojo-migrator/-/pojo-migrator-2.1.0.tgz", diff --git a/package.json b/package.json index e9383019d..aae6564a5 100644 --- a/package.json +++ b/package.json @@ -161,6 +161,7 @@ "percentile": "^1.2.0", "pify": "^3.0.0", "ping-pong-stream": "^1.0.0", + "poa-contract-metadata": "github:poanetwork/poa-contract-metadata#master", "pojo-migrator": "^2.1.0", "polyfill-crypto.getrandomvalues": "^1.0.0", "post-message-stream": "^3.0.0", @@ -318,7 +319,7 @@ "watchify": "^3.11.0" }, "engines": { - "node": "8.11.4", - "npm": "^6.1.0" + "node": "8.12.0", + "npm": "^6.4.1" } } diff --git a/ui/lib/icon-factory.js b/ui/lib/icon-factory.js index a1170bf4d..3b015eb32 100644 --- a/ui/lib/icon-factory.js +++ b/ui/lib/icon-factory.js @@ -64,4 +64,3 @@ function jsNumberForAddress (address) { var seed = parseInt(addr, 16) return seed } -