Merge remote-tracking branch 'origin/develop' into token-menu
This commit is contained in:
commit
c9efcd45b0
|
@ -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`),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
? <TokenListPlaceholder />
|
||||
|
@ -43,7 +46,7 @@ export default class InfoBox extends Component {
|
|||
<div
|
||||
className="token-list__token-icon"
|
||||
style={{
|
||||
'backgroundImage': logo && `url(images/contract/${logo})`,
|
||||
'backgroundImage': logo && `url(${imagesFolder}/${logo})`,
|
||||
}}
|
||||
>
|
||||
</div>
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
import TokenSearch from './token-search.component'
|
||||
import TokenSearch from './token-search.container'
|
||||
module.exports = TokenSearch
|
||||
|
|
|
@ -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 (
|
||||
<InputAdornment
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import { connect } from 'react-redux'
|
||||
import TokenSearch from './token-search.component'
|
||||
|
||||
const { clearPendingTokens } = require('../../../../../ui/app/actions')
|
||||
|
||||
const mapStateToProps = ({ metamask }) => {
|
||||
const { network } = metamask
|
||||
return {
|
||||
network,
|
||||
}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
clearPendingTokens: () => dispatch(clearPendingTokens()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(TokenSearch)
|
|
@ -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 (
|
||||
<div className="page-container">
|
||||
|
@ -42,7 +59,7 @@ export default class ConfirmAddToken extends Component {
|
|||
{ 'Add Tokens' /* this.context.t('addTokens')*/ }
|
||||
</h2>
|
||||
<p className="confirm-label">
|
||||
{ areMultipleTokens ? 'Would you like to add these tokens?' : 'Would you like to add this token?' /* this.context.t('likeToAddTokens')*/ }
|
||||
{ likeToAddTokensText /* this.context.t('likeToAddTokens')*/ }
|
||||
</p>
|
||||
</div>
|
||||
<div className="page-container__content">
|
||||
|
@ -71,6 +88,7 @@ export default class ConfirmAddToken extends Component {
|
|||
className="confirm-add-token__token-icon"
|
||||
diameter={48}
|
||||
address={address}
|
||||
network={network}
|
||||
/>
|
||||
<div className="confirm-add-token__name">
|
||||
{ this.getTokenName(name, symbol) }
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 () {
|
||||
|
@ -155,7 +184,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()
|
||||
|
@ -164,8 +193,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,
|
||||
|
@ -190,26 +221,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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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%'
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -64,4 +64,3 @@ function jsNumberForAddress (address) {
|
|||
var seed = parseInt(addr, 16)
|
||||
return seed
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue