Merge remote-tracking branch 'origin/develop' into trezor-ledger

This commit is contained in:
Victor Baranov 2019-01-29 14:05:05 +03:00
commit 59dbd1fde3
29 changed files with 583 additions and 315 deletions

View File

@ -1,64 +1,64 @@
const POA = 'poa'
const DAI = 'dai'
const POA_SOKOL = 'sokol'
const MAINNET = 'mainnet'
const ROPSTEN = 'ropsten' const ROPSTEN = 'ropsten'
const RINKEBY = 'rinkeby' const RINKEBY = 'rinkeby'
const KOVAN = 'kovan' const KOVAN = 'kovan'
const MAINNET = 'mainnet'
const POA_SOKOL = 'sokol'
const POA = 'poa'
const DAI = 'dai'
const LOCALHOST = 'localhost' const LOCALHOST = 'localhost'
const MAINNET_CODE = 1
const ROPSTEN_CODE = 3
const RINKEYBY_CODE = 4
const KOVAN_CODE = 42
const POA_SOKOL_CODE = 77
const POA_CODE = 99 const POA_CODE = 99
const DAI_CODE = 100 const DAI_CODE = 100
const POA_SOKOL_CODE = 77
const MAINNET_CODE = 1
const ROPSTEN_CODE = 3
const RINKEBY_CODE = 4
const KOVAN_CODE = 42
const POA_DISPLAY_NAME = 'POA Network'
const DAI_DISPLAY_NAME = 'xDai Chain'
const POA_SOKOL_DISPLAY_NAME = 'Sokol'
const MAINNET_DISPLAY_NAME = 'Main Ethereum Network'
const ROPSTEN_DISPLAY_NAME = 'Ropsten' const ROPSTEN_DISPLAY_NAME = 'Ropsten'
const RINKEBY_DISPLAY_NAME = 'Rinkeby' const RINKEBY_DISPLAY_NAME = 'Rinkeby'
const KOVAN_DISPLAY_NAME = 'Kovan' const KOVAN_DISPLAY_NAME = 'Kovan'
const POA_SOKOL_DISPLAY_NAME = 'Sokol'
const POA_DISPLAY_NAME = 'POA Network'
const DAI_DISPLAY_NAME = 'xDai Chain'
const MAINNET_DISPLAY_NAME = 'Main Ethereum Network'
const DROPDOWN_POA_DISPLAY_NAME = POA_DISPLAY_NAME
const DROPDOWN_DAI_DISPLAY_NAME = DAI_DISPLAY_NAME
const DROPDOWN_POA_SOKOL_DISPLAY_NAME = 'Sokol Network'
const DROPDOWN_MAINNET_DISPLAY_NAME = 'Main Network'
const DROPDOWN_ROPSTEN_DISPLAY_NAME = 'Ropsten Test Net' const DROPDOWN_ROPSTEN_DISPLAY_NAME = 'Ropsten Test Net'
const DROPDOWN_RINKEBY_DISPLAY_NAME = 'Rinkeby Test Net' const DROPDOWN_RINKEBY_DISPLAY_NAME = 'Rinkeby Test Net'
const DROPDOWN_KOVAN_DISPLAY_NAME = 'Kovan Test Net' const DROPDOWN_KOVAN_DISPLAY_NAME = 'Kovan Test Net'
const DROPDOWN_POA_SOKOL_DISPLAY_NAME = 'Sokol Network'
const DROPDOWN_POA_DISPLAY_NAME = POA_DISPLAY_NAME
const DROPDOWN_DAI_DISPLAY_NAME = DAI_DISPLAY_NAME
const DROPDOWN_MAINNET_DISPLAY_NAME = 'Main Network'
module.exports = { module.exports = {
POA,
DAI,
POA_SOKOL,
MAINNET,
ROPSTEN, ROPSTEN,
RINKEBY, RINKEBY,
KOVAN, KOVAN,
MAINNET,
POA_SOKOL,
POA,
DAI,
LOCALHOST, LOCALHOST,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEYBY_CODE,
KOVAN_CODE,
POA_SOKOL_CODE,
POA_CODE, POA_CODE,
DAI_CODE, DAI_CODE,
POA_SOKOL_CODE,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEBY_CODE,
KOVAN_CODE,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME,
MAINNET_DISPLAY_NAME,
ROPSTEN_DISPLAY_NAME, ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME, RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME, KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME, DROPDOWN_POA_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME, DROPDOWN_DAI_DISPLAY_NAME,
POA_DISPLAY_NAME, DROPDOWN_POA_SOKOL_DISPLAY_NAME,
DAI_DISPLAY_NAME, DROPDOWN_MAINNET_DISPLAY_NAME,
DROPDOWN_ROPSTEN_DISPLAY_NAME, DROPDOWN_ROPSTEN_DISPLAY_NAME,
DROPDOWN_RINKEBY_DISPLAY_NAME, DROPDOWN_RINKEBY_DISPLAY_NAME,
DROPDOWN_KOVAN_DISPLAY_NAME, DROPDOWN_KOVAN_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_MAINNET_DISPLAY_NAME,
} }

View File

@ -11,6 +11,7 @@ const createInfuraClient = require('./createInfuraClient')
const createJsonRpcClient = require('./createJsonRpcClient') const createJsonRpcClient = require('./createJsonRpcClient')
const createLocalhostClient = require('./createLocalhostClient') const createLocalhostClient = require('./createLocalhostClient')
const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy') const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy')
const ethNetProps = require('eth-net-props')
const { const {
ROPSTEN, ROPSTEN,
@ -21,10 +22,10 @@ const {
POA_SOKOL, POA_SOKOL,
POA, POA,
DAI, DAI,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
} = require('./enums') } = require('./enums')
const POA_RPC_URL = 'https://core.poa.network'
const DAI_RPC_URL = 'https://dai.poa.network'
const SOKOL_RPC_URL = 'https://sokol.poa.network'
const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET] const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET]
const env = process.env.METAMASK_ENV const env = process.env.METAMASK_ENV
@ -109,7 +110,12 @@ module.exports = class NetworkController extends EventEmitter {
async setProviderType (type) { async setProviderType (type) {
assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`) assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`)
assert(INFURA_PROVIDER_TYPES.includes(type) || type === LOCALHOST || type === POA_SOKOL || type === POA || type === DAI, `NetworkController - Unknown rpc type "${type}"`) assert(INFURA_PROVIDER_TYPES.includes(type) ||
type === LOCALHOST ||
type === POA_SOKOL ||
type === POA ||
type === DAI
, `NetworkController - Unknown rpc type "${type}"`)
const providerConfig = { type } const providerConfig = { type }
this.providerConfig = providerConfig this.providerConfig = providerConfig
} }
@ -145,11 +151,11 @@ module.exports = class NetworkController extends EventEmitter {
this._configureInfuraProvider(opts) this._configureInfuraProvider(opts)
// other type-based rpc endpoints // other type-based rpc endpoints
} else if (type === POA) { } else if (type === POA) {
this._configureStandardProvider({ rpcUrl: POA_RPC_URL }) this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0] })
} else if (type === DAI) { } else if (type === DAI) {
this._configureStandardProvider({ rpcUrl: DAI_RPC_URL }) this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0] })
} else if (type === POA_SOKOL) { } else if (type === POA_SOKOL) {
this._configureStandardProvider({ rpcUrl: SOKOL_RPC_URL }) this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0] })
} else if (type === LOCALHOST) { } else if (type === LOCALHOST) {
this._configureLocalhostProvider() this._configureLocalhostProvider()
// url-based rpc endpoints // url-based rpc endpoints

View File

@ -1,39 +1,109 @@
const { const {
POA_SOKOL,
POA, POA,
DAI,
POA_SOKOL,
MAINNET,
ROPSTEN, ROPSTEN,
RINKEBY, RINKEBY,
KOVAN, KOVAN,
MAINNET,
POA_SOKOL_CODE,
ROPSTEN_CODE,
RINKEYBY_CODE,
KOVAN_CODE,
POA_CODE, POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEBY_CODE,
KOVAN_CODE,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME, POA_SOKOL_DISPLAY_NAME,
MAINNET_DISPLAY_NAME,
ROPSTEN_DISPLAY_NAME, ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME, RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME, KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME, DROPDOWN_POA_DISPLAY_NAME,
POA_DISPLAY_NAME, DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
DROPDOWN_MAINNET_DISPLAY_NAME,
DROPDOWN_ROPSTEN_DISPLAY_NAME,
DROPDOWN_RINKEBY_DISPLAY_NAME,
DROPDOWN_KOVAN_DISPLAY_NAME,
} = require('./enums') } = require('./enums')
const networkToNameMap = { const networks = {}
[POA_SOKOL]: POA_SOKOL_DISPLAY_NAME,
[POA]: POA_SOKOL_DISPLAY_NAME,
[ROPSTEN]: ROPSTEN_DISPLAY_NAME,
[RINKEBY]: RINKEBY_DISPLAY_NAME,
[KOVAN]: KOVAN_DISPLAY_NAME,
[MAINNET]: MAINNET_DISPLAY_NAME,
[POA_SOKOL_CODE]: POA_SOKOL_DISPLAY_NAME,
[ROPSTEN_CODE]: ROPSTEN_DISPLAY_NAME,
[RINKEYBY_CODE]: RINKEBY_DISPLAY_NAME,
[KOVAN_CODE]: KOVAN_DISPLAY_NAME,
[POA_CODE]: POA_DISPLAY_NAME,
}
const getNetworkDisplayName = key => networkToNameMap[key] const POA_OBJ = {
order: 1,
providerName: POA,
networkID: POA_CODE,
displayName: POA_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_POA_DISPLAY_NAME,
}
networks[POA_CODE] = POA_OBJ
networks[POA] = POA_OBJ
const DAI_OBJ = {
order: 2,
providerName: DAI,
networkID: DAI_CODE,
displayName: DAI_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_DAI_DISPLAY_NAME,
}
networks[DAI_CODE] = DAI_OBJ
networks[DAI] = DAI_OBJ
const POA_SOKOL_OBJ = {
order: 3,
providerName: POA_SOKOL,
networkID: POA_SOKOL_CODE,
displayName: POA_SOKOL_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_POA_SOKOL_DISPLAY_NAME,
}
networks[POA_SOKOL_CODE] = POA_SOKOL_OBJ
networks[POA_SOKOL] = POA_SOKOL_OBJ
const MAINNET_OBJ = {
order: 4,
providerName: MAINNET,
networkID: MAINNET_CODE,
displayName: MAINNET_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_MAINNET_DISPLAY_NAME,
}
networks[MAINNET_CODE] = MAINNET_OBJ
networks[MAINNET] = MAINNET_OBJ
const ROPSTEN_OBJ = {
order: 5,
providerName: ROPSTEN,
networkID: ROPSTEN_CODE,
displayName: ROPSTEN_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_ROPSTEN_DISPLAY_NAME,
}
networks[ROPSTEN_CODE] = ROPSTEN_OBJ
networks[ROPSTEN] = ROPSTEN_OBJ
const KOVAN_OBJ = {
order: 6,
providerName: KOVAN,
networkID: KOVAN_CODE,
displayName: KOVAN_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_KOVAN_DISPLAY_NAME,
}
networks[KOVAN_CODE] = KOVAN_OBJ
networks[KOVAN] = KOVAN_OBJ
const RINKEBY_OBJ = {
order: 7,
providerName: RINKEBY,
networkID: RINKEBY_CODE,
displayName: RINKEBY_DISPLAY_NAME,
displayNameDropdown: DROPDOWN_RINKEBY_DISPLAY_NAME,
}
networks[RINKEBY_CODE] = RINKEBY_OBJ
networks[RINKEBY] = RINKEBY_OBJ
const getNetworkDisplayName = key => networks[key].displayName
module.exports = { module.exports = {
networks,
getNetworkDisplayName, getNetworkDisplayName,
} }

View File

@ -5,6 +5,14 @@ module.exports = {
} }
const ethNetProps = require('eth-net-props') const ethNetProps = require('eth-net-props')
const { POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEBY_CODE,
KOVAN_CODE } = require('../controllers/network/enums')
/** /**
* Gives the caller a url at which the user can acquire coin, depending on the network they are in * Gives the caller a url at which the user can acquire coin, depending on the network they are in
* *
@ -19,16 +27,16 @@ const ethNetProps = require('eth-net-props')
*/ */
function getBuyEthUrl ({ network, amount, address, ind }) { function getBuyEthUrl ({ network, amount, address, ind }) {
let url let url
switch (network) { switch (Number(network)) {
case '1': case MAINNET_CODE:
case '99': case POA_CODE:
case '100': case DAI_CODE:
url = getExchanges({network, amount, address})[ind].link url = getExchanges({network, amount, address})[ind].link
break break
case '3': case ROPSTEN_CODE:
case '4': case RINKEBY_CODE:
case '42': case KOVAN_CODE:
case '77': case POA_SOKOL_CODE:
url = getFaucets(network)[ind] url = getFaucets(network)[ind]
break break
} }
@ -85,5 +93,7 @@ function getExchanges ({network, amount, address}) {
link: 'https://dai-bridge.poa.network/', link: 'https://dai-bridge.poa.network/',
}, },
] ]
default:
return []
} }
} }

View File

@ -55,6 +55,9 @@ const sigUtil = require('eth-sig-util')
const { importTypes } = require('../../old-ui/app/accounts/import/enums') const { importTypes } = require('../../old-ui/app/accounts/import/enums')
const { LEDGER, TREZOR } = require('../../old-ui/app/components/connect-hardware/enum') const { LEDGER, TREZOR } = require('../../old-ui/app/components/connect-hardware/enum')
const { POA_CODE,
DAI_CODE,
POA_SOKOL_CODE } = require('./controllers/network/enums')
const accountsPerPage = 5 const accountsPerPage = 5
module.exports = class MetamaskController extends EventEmitter { module.exports = class MetamaskController extends EventEmitter {
@ -1512,7 +1515,7 @@ module.exports = class MetamaskController extends EventEmitter {
const networkIdStr = networkController.store.getState().network const networkIdStr = networkController.store.getState().network
const networkId = parseInt(networkIdStr) const networkId = parseInt(networkIdStr)
const isPOA = networkId === 77 || networkId === 99 const isPOA = networkId === POA_SOKOL_CODE || networkId === POA_CODE || networkId === DAI_CODE
// Return 1 gwei if using a POA network of if there are no blocks have been observed: // Return 1 gwei if using a POA network of if there are no blocks have been observed:
if (isPOA || recentBlocks.length === 0) { if (isPOA || recentBlocks.length === 0) {

View File

@ -1,6 +1,9 @@
const extension = require('extensionizer') const extension = require('extensionizer')
const explorerLinks = require('eth-net-props').explorerLinks const explorerLinks = require('eth-net-props').explorerLinks
const { capitalizeFirstLetter } = require('../lib/util') const { capitalizeFirstLetter } = require('../lib/util')
const { POA_CODE,
DAI_CODE,
POA_SOKOL_CODE } = require('../controllers/network/enums')
class ExtensionPlatform { class ExtensionPlatform {
@ -125,7 +128,10 @@ class ExtensionPlatform {
_getExplorer (hash, networkId) { _getExplorer (hash, networkId) {
let explorerName let explorerName
if (networkId === 99 || networkId === 100 || networkId === 77) { if (networkId === POA_CODE ||
networkId === DAI_CODE ||
networkId === POA_SOKOL_CODE
) {
explorerName = 'BlockScout' explorerName = 'BlockScout'
} else { } else {
explorerName = 'Etherscan' explorerName = 'Etherscan'

View File

@ -8,6 +8,14 @@ import CopyButton from '../../components/copyButton'
import ErrorComponent from '../../components/error' import ErrorComponent from '../../components/error'
import { getFullABI } from './helpers' import { getFullABI } from './helpers'
import { POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEBY_CODE,
KOVAN_CODE } from '../../../../app/scripts/controllers/network/enums'
class ContractImportView extends Component { class ContractImportView extends Component {
constructor (props) { constructor (props) {
super(props) super(props)
@ -186,6 +194,28 @@ class ContractImportView extends Component {
.catch() .catch()
} }
getBlockscoutApiNetworkSuffix () {
const { network } = this.props
switch (Number(network)) {
case MAINNET_CODE:
return 'mainnet'
case POA_CODE:
return 'core'
case POA_SOKOL_CODE:
return 'sokol'
case DAI_CODE:
return 'dai'
case KOVAN_CODE:
return 'kovan'
case ROPSTEN_CODE:
return 'ropsten'
case RINKEBY_CODE:
return 'rinkeby'
default:
return ''
}
}
clearInputs () { clearInputs () {
this.setState({ this.setState({
contractAddr: '', contractAddr: '',

View File

@ -18,6 +18,8 @@ const emptyAddr = '0x0000000000000000000000000000000000000000'
const SEARCH_TAB = 'SEARCH' const SEARCH_TAB = 'SEARCH'
const CUSTOM_TOKEN_TAB = 'CUSTOM_TOKEN' const CUSTOM_TOKEN_TAB = 'CUSTOM_TOKEN'
const { POA_CODE, MAINNET_CODE } = require('../../../../app/scripts/controllers/network/enums')
class AddTokenScreen extends Component { class AddTokenScreen extends Component {
static contextTypes = { static contextTypes = {
@ -93,8 +95,9 @@ class AddTokenScreen extends Component {
const { network } = this.props const { network } = this.props
const networkID = parseInt(network) const networkID = parseInt(network)
let views = [] let views = []
const isProdNetwork = networkID === 1 || networkID === 99 const isProdNetworkWithKnownTokens = networkID === MAINNET_CODE ||
isProdNetwork ? views = [h(TabBar, { networkID === POA_CODE
isProdNetworkWithKnownTokens ? views = [h(TabBar, {
style: { style: {
paddingTop: '0px', paddingTop: '0px',
}, },

View File

@ -9,6 +9,9 @@ const NetworkIndicator = require('./network')
const {AccountDropdowns} = require('./account-dropdowns') const {AccountDropdowns} = require('./account-dropdowns')
const ethNetProps = require('eth-net-props') const ethNetProps = require('eth-net-props')
const { LOCALHOST } = require('../../../app/scripts/controllers/network/enums')
const { networks } = require('../../../app/scripts/controllers/network/util')
const LOCALHOST_RPC_URL = 'http://localhost:8545' const LOCALHOST_RPC_URL = 'http://localhost:8545'
module.exports = class AppBar extends Component { module.exports = class AppBar extends Component {
@ -243,6 +246,35 @@ module.exports = class AppBar extends Component {
const state = this.state || {} const state = this.state || {}
const isOpen = state.isNetworkMenuOpen const isOpen = state.isNetworkMenuOpen
const networkDropdownItems = Object.keys(networks)
.filter((networkID) => {
return !isNaN(networkID)
})
.sort((networkID1, networkID2) => {
const networkObj1 = networks[networkID1]
const networkObj2 = networks[networkID2]
return networkObj1.order - networkObj2.order
})
.map((networkID) => {
const networkObj = networks[networkID]
return h(
DropdownMenuItem,
{
key: networkObj.providerName,
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType(networkObj.providerName)),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === networkObj.providerName ? 'white' : '',
},
},
[h(providerType === networkObj.providerName ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(networkID),
]
)
})
return h(Dropdown, { return h(Dropdown, {
useCssTransition: true, useCssTransition: true,
isOpen, isOpen,
@ -272,124 +304,7 @@ module.exports = class AppBar extends Component {
}, },
}, [ }, [
h( ...networkDropdownItems,
DropdownMenuItem,
{
key: 'poa',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('poa')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'poa' ? 'white' : '',
},
},
[h(providerType === 'poa' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(99),
]
),
h(
DropdownMenuItem,
{
key: 'dai',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('dai')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'dai' ? 'white' : '',
},
},
[h(providerType === 'dai' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(100),
]
),
h(
DropdownMenuItem,
{
key: 'sokol',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('sokol')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'sokol' ? 'white' : '',
},
},
[h(providerType === 'sokol' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(77),
]
),
h(
DropdownMenuItem,
{
key: 'main',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('mainnet')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'mainnet' ? 'white' : '',
},
},
[h(providerType === 'mainnet' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(1),
]
),
h(
DropdownMenuItem,
{
key: 'ropsten',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('ropsten')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'ropsten' ? 'white' : '',
},
},
[h(providerType === 'ropsten' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(3),
]
),
h(
DropdownMenuItem,
{
key: 'kovan',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('kovan')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'kovan' ? 'white' : '',
},
},
[h(providerType === 'kovan' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(42),
]
),
h(
DropdownMenuItem,
{
key: 'rinkeby',
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => props.dispatch(actions.setProviderType('rinkeby')),
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'rinkeby' ? 'white' : '',
},
},
[h(providerType === 'rinkeby' ? 'div.selected-network' : ''),
ethNetProps.props.getNetworkDisplayName(4),
]
),
h( h(
DropdownMenuItem, DropdownMenuItem,
@ -398,15 +313,15 @@ module.exports = class AppBar extends Component {
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }), closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => { onClick: () => {
props.dispatch(actions.setRpcTarget('http://localhost:8545')) props.dispatch(actions.setRpcTarget('http://localhost:8545'))
props.dispatch(actions.setProviderType('localhost')) props.dispatch(actions.setProviderType(LOCALHOST))
}, },
style: { style: {
paddingLeft: '20px', paddingLeft: '20px',
fontSize: '16px', fontSize: '16px',
color: providerType === 'localhost' ? 'white' : '', color: providerType === LOCALHOST ? 'white' : '',
}, },
}, },
[h(providerType === 'localhost' ? 'div.selected-network' : ''), [h(providerType === LOCALHOST ? 'div.selected-network' : ''),
'Localhost 8545', 'Localhost 8545',
] ]
), ),

View File

@ -8,6 +8,7 @@ import AccountPanel from './account-panel'
import RadioList from './custom-radio-list' import RadioList from './custom-radio-list'
import { getNetworkDisplayName } from '../../../app/scripts/controllers/network/util' import { getNetworkDisplayName } from '../../../app/scripts/controllers/network/util'
import { getFaucets, getExchanges } from '../../../app/scripts/lib/buy-eth-url' import { getFaucets, getExchanges } from '../../../app/scripts/lib/buy-eth-url'
import { MAINNET_CODE } from '../../../app/scripts/controllers/network/enums'
import ethNetProps from 'eth-net-props' import ethNetProps from 'eth-net-props'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { getMetaMaskAccounts } from '../../../ui/app/selectors' import { getMetaMaskAccounts } from '../../../ui/app/selectors'
@ -79,7 +80,7 @@ class BuyButtonSubview extends Component {
default: default:
return ( return (
<div className="flex-column" style={{ margin: '0px 0px 20px 30px' }}> <div className="flex-column" style={{ margin: '0px 30px 20px 30px' }}>
{ this._getBuyOptionsView(network) } { this._getBuyOptionsView(network) }
</div> </div>
) )
@ -158,8 +159,8 @@ class BuyButtonSubview extends Component {
} }
formVersionSubview () { formVersionSubview () {
const network = this.props.network const { network } = this.props
if (network === '1') { if (Number(network) === MAINNET_CODE) {
if (this.props.buyView.formView.coinbase) { if (this.props.buyView.formView.coinbase) {
return <CoinbaseForm { ...this.props } /> return <CoinbaseForm { ...this.props } />
} else if (this.props.buyView.formView.shapeshift) { } else if (this.props.buyView.formView.shapeshift) {

View File

@ -1,15 +1,16 @@
import React, { Component } from 'react' import React, { Component } from 'react'
import { formatBalance, countSignificantDecimals } from '../util' import { formatBalance, countSignificantDecimals } from '../util'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import { DAI_CODE, POA_SOKOL_CODE } from '../../../app/scripts/controllers/network/enums'
class FiatValue extends Component { class FiatValue extends Component {
render = () => { render = () => {
const props = this.props const props = this.props
let { conversionRate } = props let { conversionRate } = props
const { currentCurrency, network } = props const { currentCurrency, network } = props
const isSokol = parseInt(network) === 77 const isTestnet = parseInt(network) === POA_SOKOL_CODE
const isDai = parseInt(network) === 100 const isDai = parseInt(network) === DAI_CODE
if (isSokol) { if (isTestnet) {
conversionRate = 0 conversionRate = 0
} else if (isDai) { } else if (isDai) {
conversionRate = 1 conversionRate = 1

View File

@ -2,15 +2,7 @@ const Component = require('react').Component
const h = require('react-hyperscript') const h = require('react-hyperscript')
const inherits = require('util').inherits const inherits = require('util').inherits
const ethNetProps = require('eth-net-props') const ethNetProps = require('eth-net-props')
const { const { networks } = require('../../../app/scripts/controllers/network/util')
DROPDOWN_ROPSTEN_DISPLAY_NAME,
DROPDOWN_RINKEBY_DISPLAY_NAME,
DROPDOWN_KOVAN_DISPLAY_NAME,
DROPDOWN_POA_SOKOL_DISPLAY_NAME,
DROPDOWN_POA_DISPLAY_NAME,
DROPDOWN_DAI_DISPLAY_NAME,
DROPDOWN_MAINNET_DISPLAY_NAME,
} = require('../../../app/scripts/controllers/network/enums')
module.exports = Network module.exports = Network
@ -23,12 +15,6 @@ function Network () {
Network.prototype.render = function () { Network.prototype.render = function () {
const props = this.props const props = this.props
const { provider, network: networkNumber } = props const { provider, network: networkNumber } = props
let providerName
try {
providerName = provider.type
} catch (e) {
providerName = null
}
let displayName, hoverText let displayName, hoverText
if (networkNumber === 'loading') { if (networkNumber === 'loading') {
@ -51,26 +37,8 @@ Network.prototype.render = function () {
h('i.fa.fa-caret-down'), h('i.fa.fa-caret-down'),
]) ])
} else { } else {
if (providerName === 'mainnet' || parseInt(networkNumber) === 1) { if (networkNumber && networks[networkNumber]) {
displayName = DROPDOWN_MAINNET_DISPLAY_NAME displayName = networks[networkNumber].displayNameDropdown
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'ropsten' || parseInt(networkNumber) === 3) {
displayName = DROPDOWN_ROPSTEN_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'sokol' || parseInt(networkNumber) === 77) {
displayName = DROPDOWN_POA_SOKOL_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'kovan' || parseInt(networkNumber) === 42) {
displayName = DROPDOWN_KOVAN_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'rinkeby' || parseInt(networkNumber) === 4) {
displayName = DROPDOWN_RINKEBY_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'poa' || parseInt(networkNumber) === 99) {
displayName = DROPDOWN_POA_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else if (providerName === 'dai' || parseInt(networkNumber) === 100) {
displayName = DROPDOWN_DAI_DISPLAY_NAME
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber) hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else { } else {
displayName = 'Private Network' displayName = 'Private Network'

View File

@ -24,6 +24,7 @@ const connect = require('react-redux').connect
const abiDecoder = require('abi-decoder') const abiDecoder = require('abi-decoder')
const { tokenInfoGetter, calcTokenAmount } = require('../../../ui/app/token-util') const { tokenInfoGetter, calcTokenAmount } = require('../../../ui/app/token-util')
const BigNumber = require('bignumber.js') const BigNumber = require('bignumber.js')
const ethNetProps = require('eth-net-props')
import { getMetaMaskAccounts } from '../../../ui/app/selectors' import { getMetaMaskAccounts } from '../../../ui/app/selectors'
const MIN_GAS_PRICE_BN = new BN('0') const MIN_GAS_PRICE_BN = new BN('0')
@ -31,7 +32,7 @@ const MIN_GAS_LIMIT_BN = new BN('21000')
module.exports = connect(mapStateToProps)(PendingTx) module.exports = connect(mapStateToProps)(PendingTx)
inherits(PendingTx, Component) inherits(PendingTx, Component)
function PendingTx () { function PendingTx (props) {
Component.call(this) Component.call(this)
this.state = { this.state = {
valid: true, valid: true,
@ -40,6 +41,7 @@ function PendingTx () {
tokenSymbol: '', tokenSymbol: '',
tokenDecimals: 0, tokenDecimals: 0,
tokenDataRetrieved: false, tokenDataRetrieved: false,
coinName: ethNetProps.props.getNetworkCoinName(props.network),
} }
this.tokenInfoGetter = tokenInfoGetter() this.tokenInfoGetter = tokenInfoGetter()
} }
@ -506,7 +508,7 @@ PendingTx.prototype.render = function () {
}, 'Reset'), }, 'Reset'),
// Accept Button or Buy Button // Accept Button or Buy Button
insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, 'Buy Ether') : insufficientBalance ? h('button.btn-green', { onClick: props.buyEth }, `Buy ${this.state.coinName}`) :
h('input.confirm', { h('input.confirm', {
type: 'submit', type: 'submit',
value: 'Submit', value: 'Submit',

View File

@ -9,6 +9,7 @@ const ethUtil = require('ethereumjs-util')
const copyToClipboard = require('copy-to-clipboard') const copyToClipboard = require('copy-to-clipboard')
const actions = require('../../../ui/app/actions') const actions = require('../../../ui/app/actions')
const connect = require('react-redux').connect const connect = require('react-redux').connect
const { MAINNET_CODE } = require('../../../app/scripts/controllers/network/enums')
import { countSignificantDecimals } from '../util' import { countSignificantDecimals } from '../util'
const tokenCellDropDownPrefix = 'token-cell_dropdown_' const tokenCellDropDownPrefix = 'token-cell_dropdown_'
@ -33,7 +34,7 @@ TokenCell.prototype.render = function () {
return ( return (
h(`li#token-cell_${ind}.token-cell`, { h(`li#token-cell_${ind}.token-cell`, {
style: { style: {
cursor: network === '1' ? 'pointer' : 'default', cursor: Number(network) === MAINNET_CODE ? 'pointer' : 'default',
borderBottom: isLastTokenCell ? 'none' : '1px solid #e2e2e2', borderBottom: isLastTokenCell ? 'none' : '1px solid #e2e2e2',
padding: '20px 0', padding: '20px 0',
margin: '0 30px', margin: '0 30px',

View File

@ -15,6 +15,15 @@ const ethNetProps = require('eth-net-props')
const TransactionIcon = require('./transaction-list-item-icon') const TransactionIcon = require('./transaction-list-item-icon')
const ShiftListItem = require('./shift-list-item') const ShiftListItem = require('./shift-list-item')
const { POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEBY_CODE,
KOVAN_CODE,
} = require('../../../app/scripts/controllers/network/enums')
const mapDispatchToProps = dispatch => { const mapDispatchToProps = dispatch => {
return { return {
retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)), retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)),
@ -59,13 +68,19 @@ TransactionListItem.prototype.render = function () {
const { transaction, network, conversionRate, currentCurrency } = this.props const { transaction, network, conversionRate, currentCurrency } = this.props
const { status } = transaction const { status } = transaction
if (transaction.key === 'shapeshift') { if (transaction.key === 'shapeshift') {
if (network === '1') return h(ShiftListItem, transaction) if (Number(network) === MAINNET_CODE) return h(ShiftListItem, transaction)
} }
var date = formatDate(transaction.time) var date = formatDate(transaction.time)
let isLinkable = false let isLinkable = false
const numericNet = parseInt(network) const numericNet = parseInt(network)
isLinkable = numericNet === 1 || numericNet === 3 || numericNet === 4 || numericNet === 42 || numericNet === 77 || numericNet === 99 || numericNet === 100 isLinkable = numericNet === MAINNET_CODE ||
numericNet === ROPSTEN_CODE ||
numericNet === RINKEBY_CODE ||
numericNet === KOVAN_CODE ||
numericNet === POA_SOKOL_CODE ||
numericNet === POA_CODE ||
numericNet === DAI_CODE
var isMsg = ('msgParams' in transaction) var isMsg = ('msgParams' in transaction)
var isTx = ('txParams' in transaction) var isTx = ('txParams' in transaction)

View File

@ -3,6 +3,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits const inherits = require('util').inherits
const TransactionListItem = require('./transaction-list-item') const TransactionListItem = require('./transaction-list-item')
const { MAINNET_CODE } = require('../../../app/scripts/controllers/network/enums')
module.exports = TransactionList module.exports = TransactionList
@ -16,7 +17,7 @@ TransactionList.prototype.render = function () {
const { transactions, network, unapprovedMsgs, conversionRate } = this.props const { transactions, network, unapprovedMsgs, conversionRate } = this.props
var shapeShiftTxList var shapeShiftTxList
if (network === '1') { if (Number(network) === MAINNET_CODE) {
shapeShiftTxList = this.props.shapeShiftTxList shapeShiftTxList = this.props.shapeShiftTxList
} }
const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList) const txsToRender = !shapeShiftTxList ? transactions.concat(unapprovedMsgs) : transactions.concat(unapprovedMsgs, shapeShiftTxList)

View File

@ -13,6 +13,7 @@ import PendingMsg from './components/pending-msg'
import PendingPersonalMsg from './components/pending-personal-msg' import PendingPersonalMsg from './components/pending-personal-msg'
import PendingTypedMsg from './components/pending-typed-msg' import PendingTypedMsg from './components/pending-typed-msg'
const Loading = require('./components/loading') const Loading = require('./components/loading')
const { DAI_CODE, POA_SOKOL_CODE } = require('../../app/scripts/controllers/network/enums')
const { getMetaMaskAccounts } = require('../../ui/app/selectors') const { getMetaMaskAccounts } = require('../../ui/app/selectors')
module.exports = connect(mapStateToProps)(ConfirmTxScreen) module.exports = connect(mapStateToProps)(ConfirmTxScreen)
@ -56,9 +57,9 @@ ConfirmTxScreen.prototype.render = function () {
unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, blockGasLimit } = props unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, blockGasLimit } = props
let { conversionRate } = props let { conversionRate } = props
const isSokol = parseInt(network) === 77 const isTestnet = parseInt(network) === POA_SOKOL_CODE
const isDai = parseInt(network) === 100 const isDai = parseInt(network) === DAI_CODE
if (isSokol) { if (isTestnet) {
conversionRate = 0 conversionRate = 0
} else if (isDai) { } else if (isDai) {
conversionRate = 1 conversionRate = 1

View File

@ -12,6 +12,7 @@ const validUrl = require('valid-url')
const exportAsFile = require('./util').exportAsFile const exportAsFile = require('./util').exportAsFile
const Modal = require('../../ui/app/components/modals/index').Modal const Modal = require('../../ui/app/components/modals/index').Modal
const ethNetProps = require('eth-net-props') const ethNetProps = require('eth-net-props')
const { networks } = require('../../app/scripts/controllers/network/util')
module.exports = connect(mapStateToProps)(ConfigScreen) module.exports = connect(mapStateToProps)(ConfigScreen)
@ -290,46 +291,12 @@ function currentProviderDisplay (metamaskState, state) {
const provider = metamaskState.provider const provider = metamaskState.provider
let title, value let title, value
switch (provider.type) { if (networks[provider.type]) {
title = 'Current Network'
case 'mainnet': value = ethNetProps.props.getNetworkDisplayName(networks[provider.type].networkID)
title = 'Current Network' } else {
value = ethNetProps.props.getNetworkDisplayName(1) title = 'Current RPC'
break value = metamaskState.provider.rpcTarget
case 'sokol':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(77)
break
case 'ropsten':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(3)
break
case 'kovan':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(42)
break
case 'rinkeby':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(4)
break
case 'poa':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(99)
break
case 'dai':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(100)
break
default:
title = 'Current RPC'
value = metamaskState.provider.rpcTarget
} }
return h('div', [ return h('div', [

View File

@ -210,6 +210,9 @@ function normalizeEthStringToWei (str) {
while (decimal.length < 18) { while (decimal.length < 18) {
decimal += '0' decimal += '0'
} }
if (decimal.length > 18) {
decimal = decimal.slice(0, 18)
}
const decimalBN = new ethUtil.BN(decimal, 10) const decimalBN = new ethUtil.BN(decimal, 10)
eth = eth.add(decimalBN) eth = eth.add(decimalBN)
} }

6
package-lock.json generated
View File

@ -10703,9 +10703,9 @@
} }
}, },
"eth-net-props": { "eth-net-props": {
"version": "1.0.10", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.10.tgz", "resolved": "https://registry.npmjs.org/eth-net-props/-/eth-net-props-1.0.11.tgz",
"integrity": "sha512-sCKttmHUFficRcyx95CWUW2AuvQ6rEboy4XcoR49HU7UNMxOdRti3rFyGrkVepRozn1bLLjet/doPKnj8rDG7g==", "integrity": "sha512-D5BJCoRAf0Q40X4tb0IN8goZTddYwtKqRBYklglS36iPd0qXu183NktYJ63e+1dLzeBG5vvkqN9LXW9CbLxhOQ==",
"requires": { "requires": {
"chai": "^4.1.2" "chai": "^4.1.2"
} }

View File

@ -118,7 +118,7 @@
"eth-keychain-controller": "github:vbaranov/KeyringController#simple-address", "eth-keychain-controller": "github:vbaranov/KeyringController#simple-address",
"eth-ledger-bridge-keyring": "github:vbaranov/eth-ledger-bridge-keyring#0.1.0-clear-accounts-flag", "eth-ledger-bridge-keyring": "github:vbaranov/eth-ledger-bridge-keyring#0.1.0-clear-accounts-flag",
"eth-method-registry": "^1.0.0", "eth-method-registry": "^1.0.0",
"eth-net-props": "^1.0.10", "eth-net-props": "^1.0.11",
"eth-phishing-detect": "^1.1.4", "eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.2", "eth-query": "^2.1.2",
"eth-sig-util": "^2.0.2", "eth-sig-util": "^2.0.2",

View File

@ -305,6 +305,7 @@ module.exports = {
}, },
// balance: By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)'), // balance: By.css('#app-content > div > div.app-primary.from-right > div > div > div.flex-row > div.ether-balance.ether-balance-amount > div > div > div:nth-child(1) > div:nth-child(1)'),
balance: By.xpath('//*[@id="app-content"]/div/div[2]/div/div/div[2]/div[1]/div/div/div[1]/div[1]'), balance: By.xpath('//*[@id="app-content"]/div/div[2]/div/div/div[2]/div[1]/div/div/div[1]/div[1]'),
balanceUSD: By.xpath('//*[@id="app-content"]/div/div[2]/div/div/div[2]/div[1]/div/div/div[2]/div[1]'),
address: By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div'), address: By.css('#app-content > div > div.app-primary.from-left > div > div > div:nth-child(1) > flex-column > div.flex-row > div'),
tokens: { tokens: {
menu: By.id('wallet-view__tab-tokens'), menu: By.id('wallet-view__tab-tokens'),
@ -322,6 +323,7 @@ module.exports = {
}, },
buyEther: { buyEther: {
title: By.className('flex-center buy-title'), title: By.className('flex-center buy-title'),
buttonArrow: By.className('fa fa-arrow-left fa-lg cursor-pointer'),
}, },
info: { info: {
title: By.className('section-title flex-row flex-center'), title: By.className('section-title flex-row flex-center'),

View File

@ -141,7 +141,7 @@ const addCustomToken = async (f, account1, account2) => {
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in SOKOL network', async () => { it('token should not be displayed in SOKOL testnet', async () => {
await f.setProvider(NETWORKS.SOKOL) await f.setProvider(NETWORKS.SOKOL)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
@ -151,17 +151,17 @@ const addCustomToken = async (f, account1, account2) => {
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in ROPSTEN network', async () => { it('token should not be displayed in ROPSTEN testnet', async () => {
await f.setProvider(NETWORKS.ROPSTEN) await f.setProvider(NETWORKS.ROPSTEN)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in KOVAN network', async () => { it('token should not be displayed in KOVAN testnet', async () => {
await f.setProvider(NETWORKS.KOVAN) await f.setProvider(NETWORKS.KOVAN)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in RINKEBY network', async () => { it('token should not be displayed in RINKEBY testnet', async () => {
await f.setProvider(NETWORKS.RINKEBY) await f.setProvider(NETWORKS.RINKEBY)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
@ -175,34 +175,34 @@ const addCustomToken = async (f, account1, account2) => {
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network')
}) })
it('can not add inexistent token to SOKOL network', async () => { it('can not add inexistent token to SOKOL testnet', async () => {
await f.setProvider(NETWORKS.SOKOL) await f.setProvider(NETWORKS.SOKOL)
assert(await f.isDisabledAddInexistentToken(inexistentToken), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(inexistentToken), true, 'can add inexistent token in SOKOL testnet')
}) })
it('can not add inexistent token to ROPSTEN network', async () => { it('can not add inexistent token to ROPSTEN testnet', async () => {
await f.setProvider(NETWORKS.ROPSTEN) await f.setProvider(NETWORKS.ROPSTEN)
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in ROPSTEN testnet')
}) })
it('can not add inexistent token to KOVAN network', async () => { it('can not add inexistent token to KOVAN testnet', async () => {
await f.setProvider(NETWORKS.KOVAN) await f.setProvider(NETWORKS.KOVAN)
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in KOVAN testnet')
}) })
it('can not add inexistent token to RINKEBY network', async () => { it('can not add inexistent token to RINKEBY testnet', async () => {
await f.setProvider(NETWORKS.RINKEBY) await f.setProvider(NETWORKS.RINKEBY)
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in RINKEBY testnet')
}) })
it('can not add inexistent token to MAINNET', async () => { it('can not add inexistent token to MAINNET', async () => {
await f.setProvider(NETWORKS.MAINNET) await f.setProvider(NETWORKS.MAINNET)
assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress), true, 'can add inexistent token in MAINNET')
}) })
it('can not add inexistent token to LOCALHOST network', async () => { it('can not add inexistent token to LOCALHOST network', async () => {
await f.setProvider(NETWORKS.LOCALHOST) await f.setProvider(NETWORKS.LOCALHOST)
assert(await f.isDisabledAddInexistentToken(tokenAddress.slice(0, tokenAddress.length - 2) + '0'), true, 'can add inexistent token in POA network') assert(await f.isDisabledAddInexistentToken(tokenAddress.slice(0, tokenAddress.length - 2) + '0'), true, 'can add inexistent token in LOCALHOST network')
}) })
it('token still should be displayed in LOCALHOST network', async () => { it('token still should be displayed in LOCALHOST network', async () => {
@ -412,7 +412,7 @@ const addCustomToken = async (f, account1, account2) => {
}) })
}) })
describe('Remove token , provider is localhost', function () { describe('Remove token, provider is localhost', function () {
it('switch to account 1 ', async () => { it('switch to account 1 ', async () => {
const accountMenu = await f.waitUntilShowUp(menus.account.menu) const accountMenu = await f.waitUntilShowUp(menus.account.menu)

View File

@ -226,7 +226,7 @@ const addTokeFromSearch = async (f) => {
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in SOKOL network', async () => { it('token should not be displayed in SOKOL testnet', async () => {
await f.setProvider(NETWORKS.SOKOL) await f.setProvider(NETWORKS.SOKOL)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
@ -236,17 +236,17 @@ const addTokeFromSearch = async (f) => {
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in ROPSTEN network', async () => { it('token should not be displayed in ROPSTEN testnet', async () => {
await f.setProvider(NETWORKS.ROPSTEN) await f.setProvider(NETWORKS.ROPSTEN)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in KOVAN network', async () => { it('token should not be displayed in KOVAN testnet', async () => {
await f.setProvider(NETWORKS.KOVAN) await f.setProvider(NETWORKS.KOVAN)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })
it('token should not be displayed in RINKEBY network', async () => { it('token should not be displayed in RINKEBY testnet', async () => {
await f.setProvider(NETWORKS.RINKEBY) await f.setProvider(NETWORKS.RINKEBY)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed') assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
}) })

View File

@ -63,7 +63,7 @@ const customRPC = async (f) => {
await f.clearField(fieldRpc) await f.clearField(fieldRpc)
await fieldRpc.sendKeys(correctRpcUrl + 0) await fieldRpc.sendKeys(correctRpcUrl + 0)
await f.driver.findElement(screens.settings.buttonSave).click() await f.driver.findElement(screens.settings.buttonSave).click()
await f.delay(10000) await f.delay(20000)
const customUrlElement = await f.waitUntilShowUp(screens.settings.currentNetwork) const customUrlElement = await f.waitUntilShowUp(screens.settings.currentNetwork)
assert.equal(await customUrlElement.getText(), correctRpcUrl + 0, 'Added Url doesn\'t match') assert.equal(await customUrlElement.getText(), correctRpcUrl + 0, 'Added Url doesn\'t match')
}) })

View File

@ -773,17 +773,17 @@ const importContractAccount = async (f, account1, getCreatedAccounts) => {
assert.notEqual(reject, false, "button reject isn't displayed") assert.notEqual(reject, false, "button reject isn't displayed")
}) })
it("Button 'Buy Ether' is displayed", async () => { it("Button 'Buy POA' is displayed", async function () {
const button = await f.waitUntilShowUp(screens.confirmTransaction.button.buyEther) const button = await f.waitUntilShowUp(screens.confirmTransaction.button.buyEther)
assert.equal(await button.getText(), 'Buy Ether', 'button has incorrect name') assert.equal(await button.getText(), 'Buy POA', 'button has incorrect name')
assert.equal(await button.isEnabled(), true, 'button is disabled') assert.equal(await button.isEnabled(), true, 'button is disabled')
}) })
it("Open screen 'Buy Ether'", async () => { it("Open screen 'Buy'", async function () {
const button = await f.waitUntilShowUp(screens.confirmTransaction.button.buyEther) const button = await f.waitUntilShowUp(screens.confirmTransaction.button.buyEther)
await button.click() await button.click()
const title = await f.waitUntilShowUp(screens.buyEther.title) const title = await f.waitUntilShowUp(screens.buyEther.title)
assert.equal(await title.getText(), 'Buy POA', "screen 'Buy Ether' has incorrect title text") assert.equal(await title.getText(), 'Buy POA', "screen 'Buy POA' has incorrect title text")
const arrow = await f.waitUntilShowUp(elements.buttonArrow) const arrow = await f.waitUntilShowUp(elements.buttonArrow)
await arrow.click() await arrow.click()
}) })

View File

@ -4,7 +4,19 @@ const {
getCurrentKeyring, getCurrentKeyring,
ifLooseAcc, ifLooseAcc,
ifContractAcc, ifContractAcc,
addressSummary,
isValidAddress,
numericBalance,
parseBalance,
formatBalance,
normalizeToWei,
normalizeEthStringToWei,
normalizeNumberToWei,
isHex,
} = require('../../../../old-ui/app/util') } = require('../../../../old-ui/app/util')
const ethUtil = require('ethereumjs-util')
let ethInWei = '1'
for (let i = 0; i < 18; i++) { ethInWei += '0' }
describe('countSignificantDecimals(val, len) function', () => { describe('countSignificantDecimals(val, len) function', () => {
it('returns correct significant decimals', () => { it('returns correct significant decimals', () => {
@ -74,3 +86,247 @@ describe('ifContractAcc(keyring) function', () => {
assert.equal(false, ifContractAcc({})) assert.equal(false, ifContractAcc({}))
}) })
}) })
describe('#addressSummary', function () {
it('should add case-sensitive checksum', function () {
const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'
const result = addressSummary(address)
assert.equal(result, '0xFDEa65C8...b825')
})
it('should accept arguments for firstseg, lastseg, and keepPrefix', function () {
const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'
const result = addressSummary(address, 4, 4, false)
assert.equal(result, 'FDEa...b825')
})
})
describe('#isValidAddress', function () {
it('should allow 40-char non-prefixed hex', function () {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b825'
const result = isValidAddress(address)
assert.ok(result)
})
it('should allow 42-char non-prefixed hex', function () {
const address = '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825'
const result = isValidAddress(address)
assert.ok(result)
})
it('should not allow less non hex-prefixed', function () {
const address = 'fdea65c8e26263f6d9a1b5de9555d2931a33b85'
const result = isValidAddress(address)
assert.ok(!result)
})
it('should not allow less hex-prefixed', function () {
const address = '0xfdea65ce26263f6d9a1b5de9555d2931a33b85'
const result = isValidAddress(address)
assert.ok(!result)
})
it('should recognize correct capitalized checksum', function () {
const address = '0xFDEa65C8e26263F6d9A1B5de9555D2931A33b825'
const result = isValidAddress(address)
assert.ok(result)
})
it('should recognize incorrect capitalized checksum', function () {
const address = '0xFDea65C8e26263F6d9A1B5de9555D2931A33b825'
const result = isValidAddress(address)
assert.ok(!result)
})
it('should recognize this sample hashed address', function () {
const address = '0x5Fda30Bb72B8Dfe20e48A00dFc108d0915BE9Bb0'
const result = isValidAddress(address)
const hashed = ethUtil.toChecksumAddress(address.toLowerCase())
assert.equal(hashed, address, 'example is hashed correctly')
assert.ok(result, 'is valid by our check')
})
})
describe('#numericBalance', function () {
it('should return a BN 0 if given nothing', function () {
const result = numericBalance()
assert.equal(result.toString(10), 0)
})
it('should work with hex prefix', function () {
const result = numericBalance('0x012')
assert.equal(result.toString(10), '18')
})
it('should work with no hex prefix', function () {
const result = numericBalance('012')
assert.equal(result.toString(10), '18')
})
})
describe('#parseBalance', function () {
it('should render 0.01 eth correctly', function () {
const input = '0x2386F26FC10000'
const output = parseBalance(input)
assert.deepEqual(output, ['0', '01'])
})
it('should render 12.023 eth correctly', function () {
const input = 'A6DA46CCA6858000'
const output = parseBalance(input)
assert.deepEqual(output, ['12', '023'])
})
it('should render 0.0000000342422 eth correctly', function () {
const input = '0x7F8FE81C0'
const output = parseBalance(input)
assert.deepEqual(output, ['0', '0000000342422'])
})
it('should render 0 eth correctly', function () {
const input = '0x0'
const output = parseBalance(input)
assert.deepEqual(output, ['0', '0'])
})
})
describe('formatBalance function', function () {
it('when given nothing', function () {
const result = formatBalance()
assert.equal(result, '0', 'should return "None"')
})
it('should return eth as string followed by ETH', function () {
const input = new ethUtil.BN(ethInWei, 10).toJSON()
console.log('input = ', input)
const result = formatBalance(input, 4)
assert.equal(result, '1.0000 ETH')
})
it('should return eth as string followed by ETH', function () {
const input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON()
console.log('input = ', input)
const result = formatBalance(input, 3)
assert.equal(result, '0.500 ETH')
})
it('should display specified decimal points', function () {
const input = '0x128dfa6a90b28000'
const result = formatBalance(input, 2)
assert.equal(result, '1.33 ETH')
})
it('should default to 3 decimal points', function () {
const input = '0x128dfa6a90b28000'
const result = formatBalance(input)
assert.equal(result, '1.337 ETH')
})
it('should show 2 significant digits for tiny balances', function () {
const input = '0x1230fa6a90b28'
const result = formatBalance(input)
assert.equal(result, '0.00032 ETH')
})
it('should not parse the balance and return value with 2 decimal points with ETH at the end', function () {
const value = '1.2456789'
const needsParse = false
const result = formatBalance(value, 2, needsParse)
assert.equal(result, '1.24 ETH')
})
})
describe('normalizing values', function () {
describe('#normalizeToWei', function () {
it('should convert an eth to the appropriate equivalent values', function () {
var valueTable = {
wei: '1000000000000000000',
kwei: '1000000000000000',
mwei: '1000000000000',
gwei: '1000000000',
szabo: '1000000',
finney: '1000',
ether: '1',
// kether:'0.001',
// mether:'0.000001',
// AUDIT: We're getting BN numbers on these ones.
// I think they're big enough to ignore for now.
// gether:'0.000000001',
// tether:'0.000000000001',
}
var oneEthBn = new ethUtil.BN(ethInWei, 10)
for (var currency in valueTable) {
var value = new ethUtil.BN(valueTable[currency], 10)
var output = normalizeToWei(value, currency)
assert.equal(output.toString(10), valueTable.wei, `value of ${output.toString(10)} ${currency} should convert to ${oneEthBn}`)
}
})
})
describe('#normalizeEthStringToWei', function () {
it('should convert decimal eth to pure wei BN', function () {
var input = '1.23456789'
var output = normalizeEthStringToWei(input)
assert.equal(output.toString(10), '1234567890000000000')
})
it('should convert 1 to expected wei', function () {
var input = '1'
var output = normalizeEthStringToWei(input)
assert.equal(output.toString(10), ethInWei)
})
it('should account for overflow numbers gracefully by dropping extra precision.', function () {
var input = '1.11111111111111111111'
var output = normalizeEthStringToWei(input)
assert.equal(output.toString(10), '1111111111111111111')
})
it('should not truncate very exact wei values that do not have extra precision.', function () {
var input = '1.100000000000000001'
var output = normalizeEthStringToWei(input)
assert.equal(output.toString(10), '1100000000000000001')
})
})
describe('#normalizeNumberToWei', function () {
it('should handle a simple use case', function () {
var input = 0.0002
var output = normalizeNumberToWei(input, 'ether')
var str = output.toString(10)
assert.equal(str, '200000000000000')
})
it('should convert a kwei number to the appropriate equivalent wei', function () {
var result = normalizeNumberToWei(1.111, 'kwei')
assert.equal(result.toString(10), '1111', 'accepts decimals')
})
it('should convert a ether number to the appropriate equivalent wei', function () {
var result = normalizeNumberToWei(1.111, 'ether')
assert.equal(result.toString(10), '1111000000000000000', 'accepts decimals')
})
})
describe('#isHex', function () {
it('should return true when given a hex string', function () {
var result = isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2')
assert(result)
})
it('should return false when given a non-hex string', function () {
var result = isHex('c3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714imnotreal')
assert(!result)
})
it('should return false when given a string containing a non letter/number character', function () {
var result = isHex('c3ab8ff13720!8ad9047dd39466b3c%8974e592c2fa383d4a396071imnotreal')
assert(!result)
})
it('should return true when given a hex string with hex-prefix', function () {
var result = isHex('0xc3ab8ff13720e8ad9047dd39466b3c8974e592c2fa383d4a3960714caef0c4f2')
assert(result)
})
})
})

View File

@ -128,12 +128,14 @@ describe('util', function () {
it('should return eth as string followed by ETH', function () { it('should return eth as string followed by ETH', function () {
var input = new ethUtil.BN(ethInWei, 10).toJSON() var input = new ethUtil.BN(ethInWei, 10).toJSON()
console.log('input = ', input)
var result = util.formatBalance(input, 4) var result = util.formatBalance(input, 4)
assert.equal(result, '1.0000 ETH') assert.equal(result, '1.0000 ETH')
}) })
it('should return eth as string followed by ETH', function () { it('should return eth as string followed by ETH', function () {
var input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON() var input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON()
console.log('input = ', input)
var result = util.formatBalance(input, 3) var result = util.formatBalance(input, 3)
assert.equal(result, '0.500 ETH') assert.equal(result, '0.500 ETH')
}) })

View File

@ -11,6 +11,9 @@ const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../i18n-helper') const { fetchLocale } = require('../i18n-helper')
const log = require('loglevel') const log = require('loglevel')
const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../app/scripts/lib/enums') const { ENVIRONMENT_TYPE_NOTIFICATION } = require('../../app/scripts/lib/enums')
const { POA,
DAI,
POA_SOKOL } = require('../../app/scripts/controllers/network/enums')
const { hasUnconfirmedTransactions } = require('./helpers/confirm-transaction/util') const { hasUnconfirmedTransactions } = require('./helpers/confirm-transaction/util')
const WebcamUtils = require('../lib/webcam-utils') const WebcamUtils = require('../lib/webcam-utils')
@ -2007,7 +2010,9 @@ function setProviderType (type) {
dispatch(actions.setSelectedToken()) dispatch(actions.setSelectedToken())
}) })
const newCoin = type === 'poa' || type === 'sokol' ? 'poa' : type === 'dai' ? 'dai' : 'eth' const newCoin = type === POA || type === POA_SOKOL ?
'poa' : type === DAI ?
'dai' : 'eth'
background.setCurrentCoin(newCoin, (err, data) => { background.setCurrentCoin(newCoin, (err, data) => {
if (err) { if (err) {
log.error(err.stack) log.error(err.stack)