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 RINKEBY = 'rinkeby'
const KOVAN = 'kovan'
const MAINNET = 'mainnet'
const POA_SOKOL = 'sokol'
const POA = 'poa'
const DAI = 'dai'
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 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 RINKEBY_DISPLAY_NAME = 'Rinkeby'
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_RINKEBY_DISPLAY_NAME = 'Rinkeby 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 = {
POA,
DAI,
POA_SOKOL,
MAINNET,
ROPSTEN,
RINKEBY,
KOVAN,
MAINNET,
POA_SOKOL,
POA,
DAI,
LOCALHOST,
MAINNET_CODE,
ROPSTEN_CODE,
RINKEYBY_CODE,
KOVAN_CODE,
POA_SOKOL_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,
MAINNET_DISPLAY_NAME,
ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME,
POA_SOKOL_DISPLAY_NAME,
POA_DISPLAY_NAME,
DAI_DISPLAY_NAME,
DROPDOWN_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,
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 createLocalhostClient = require('./createLocalhostClient')
const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy')
const ethNetProps = require('eth-net-props')
const {
ROPSTEN,
@ -21,10 +22,10 @@ const {
POA_SOKOL,
POA,
DAI,
POA_CODE,
DAI_CODE,
POA_SOKOL_CODE,
} = 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 env = process.env.METAMASK_ENV
@ -109,7 +110,12 @@ module.exports = class NetworkController extends EventEmitter {
async setProviderType (type) {
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 }
this.providerConfig = providerConfig
}
@ -145,11 +151,11 @@ module.exports = class NetworkController extends EventEmitter {
this._configureInfuraProvider(opts)
// other type-based rpc endpoints
} else if (type === POA) {
this._configureStandardProvider({ rpcUrl: POA_RPC_URL })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0] })
} else if (type === DAI) {
this._configureStandardProvider({ rpcUrl: DAI_RPC_URL })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0] })
} else if (type === POA_SOKOL) {
this._configureStandardProvider({ rpcUrl: SOKOL_RPC_URL })
this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0] })
} else if (type === LOCALHOST) {
this._configureLocalhostProvider()
// url-based rpc endpoints

View File

@ -1,39 +1,109 @@
const {
POA_SOKOL,
POA,
DAI,
POA_SOKOL,
MAINNET,
ROPSTEN,
RINKEBY,
KOVAN,
MAINNET,
POA_SOKOL_CODE,
ROPSTEN_CODE,
RINKEYBY_CODE,
KOVAN_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,
MAINNET_DISPLAY_NAME,
ROPSTEN_DISPLAY_NAME,
RINKEBY_DISPLAY_NAME,
KOVAN_DISPLAY_NAME,
MAINNET_DISPLAY_NAME,
POA_DISPLAY_NAME,
DROPDOWN_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')
const networkToNameMap = {
[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 networks = {}
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 = {
networks,
getNetworkDisplayName,
}

View File

@ -5,6 +5,14 @@ module.exports = {
}
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
*
@ -19,16 +27,16 @@ const ethNetProps = require('eth-net-props')
*/
function getBuyEthUrl ({ network, amount, address, ind }) {
let url
switch (network) {
case '1':
case '99':
case '100':
switch (Number(network)) {
case MAINNET_CODE:
case POA_CODE:
case DAI_CODE:
url = getExchanges({network, amount, address})[ind].link
break
case '3':
case '4':
case '42':
case '77':
case ROPSTEN_CODE:
case RINKEBY_CODE:
case KOVAN_CODE:
case POA_SOKOL_CODE:
url = getFaucets(network)[ind]
break
}
@ -85,5 +93,7 @@ function getExchanges ({network, amount, address}) {
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 { 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
module.exports = class MetamaskController extends EventEmitter {
@ -1512,7 +1515,7 @@ module.exports = class MetamaskController extends EventEmitter {
const networkIdStr = networkController.store.getState().network
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:
if (isPOA || recentBlocks.length === 0) {

View File

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

View File

@ -8,6 +8,14 @@ import CopyButton from '../../components/copyButton'
import ErrorComponent from '../../components/error'
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 {
constructor (props) {
super(props)
@ -186,6 +194,28 @@ class ContractImportView extends Component {
.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 () {
this.setState({
contractAddr: '',

View File

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

View File

@ -9,6 +9,9 @@ const NetworkIndicator = require('./network')
const {AccountDropdowns} = require('./account-dropdowns')
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'
module.exports = class AppBar extends Component {
@ -243,6 +246,35 @@ module.exports = class AppBar extends Component {
const state = this.state || {}
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, {
useCssTransition: true,
isOpen,
@ -272,124 +304,7 @@ module.exports = class AppBar extends Component {
},
}, [
h(
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),
]
),
...networkDropdownItems,
h(
DropdownMenuItem,
@ -398,15 +313,15 @@ module.exports = class AppBar extends Component {
closeMenu: () => this.setState({ isNetworkMenuOpen: !isOpen }),
onClick: () => {
props.dispatch(actions.setRpcTarget('http://localhost:8545'))
props.dispatch(actions.setProviderType('localhost'))
props.dispatch(actions.setProviderType(LOCALHOST))
},
style: {
paddingLeft: '20px',
fontSize: '16px',
color: providerType === 'localhost' ? 'white' : '',
color: providerType === LOCALHOST ? 'white' : '',
},
},
[h(providerType === 'localhost' ? 'div.selected-network' : ''),
[h(providerType === LOCALHOST ? 'div.selected-network' : ''),
'Localhost 8545',
]
),

View File

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

View File

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

View File

@ -2,15 +2,7 @@ const Component = require('react').Component
const h = require('react-hyperscript')
const inherits = require('util').inherits
const ethNetProps = require('eth-net-props')
const {
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')
const { networks } = require('../../../app/scripts/controllers/network/util')
module.exports = Network
@ -23,12 +15,6 @@ function Network () {
Network.prototype.render = function () {
const props = this.props
const { provider, network: networkNumber } = props
let providerName
try {
providerName = provider.type
} catch (e) {
providerName = null
}
let displayName, hoverText
if (networkNumber === 'loading') {
@ -51,26 +37,8 @@ Network.prototype.render = function () {
h('i.fa.fa-caret-down'),
])
} else {
if (providerName === 'mainnet' || parseInt(networkNumber) === 1) {
displayName = DROPDOWN_MAINNET_DISPLAY_NAME
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
if (networkNumber && networks[networkNumber]) {
displayName = networks[networkNumber].displayNameDropdown
hoverText = ethNetProps.props.getNetworkDisplayName(networkNumber)
} else {
displayName = 'Private Network'

View File

@ -24,6 +24,7 @@ const connect = require('react-redux').connect
const abiDecoder = require('abi-decoder')
const { tokenInfoGetter, calcTokenAmount } = require('../../../ui/app/token-util')
const BigNumber = require('bignumber.js')
const ethNetProps = require('eth-net-props')
import { getMetaMaskAccounts } from '../../../ui/app/selectors'
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)
inherits(PendingTx, Component)
function PendingTx () {
function PendingTx (props) {
Component.call(this)
this.state = {
valid: true,
@ -40,6 +41,7 @@ function PendingTx () {
tokenSymbol: '',
tokenDecimals: 0,
tokenDataRetrieved: false,
coinName: ethNetProps.props.getNetworkCoinName(props.network),
}
this.tokenInfoGetter = tokenInfoGetter()
}
@ -506,7 +508,7 @@ PendingTx.prototype.render = function () {
}, 'Reset'),
// 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', {
type: 'submit',
value: 'Submit',

View File

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

View File

@ -15,6 +15,15 @@ const ethNetProps = require('eth-net-props')
const TransactionIcon = require('./transaction-list-item-icon')
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 => {
return {
retryTransaction: transactionId => dispatch(actions.retryTransaction(transactionId)),
@ -59,13 +68,19 @@ TransactionListItem.prototype.render = function () {
const { transaction, network, conversionRate, currentCurrency } = this.props
const { status } = transaction
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)
let isLinkable = false
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 isTx = ('txParams' in transaction)

View File

@ -3,6 +3,7 @@ const h = require('react-hyperscript')
const inherits = require('util').inherits
const TransactionListItem = require('./transaction-list-item')
const { MAINNET_CODE } = require('../../../app/scripts/controllers/network/enums')
module.exports = TransactionList
@ -16,7 +17,7 @@ TransactionList.prototype.render = function () {
const { transactions, network, unapprovedMsgs, conversionRate } = this.props
var shapeShiftTxList
if (network === '1') {
if (Number(network) === MAINNET_CODE) {
shapeShiftTxList = this.props.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 PendingTypedMsg from './components/pending-typed-msg'
const Loading = require('./components/loading')
const { DAI_CODE, POA_SOKOL_CODE } = require('../../app/scripts/controllers/network/enums')
const { getMetaMaskAccounts } = require('../../ui/app/selectors')
module.exports = connect(mapStateToProps)(ConfirmTxScreen)
@ -56,9 +57,9 @@ ConfirmTxScreen.prototype.render = function () {
unapprovedMsgs, unapprovedPersonalMsgs, unapprovedTypedMessages, blockGasLimit } = props
let { conversionRate } = props
const isSokol = parseInt(network) === 77
const isDai = parseInt(network) === 100
if (isSokol) {
const isTestnet = parseInt(network) === POA_SOKOL_CODE
const isDai = parseInt(network) === DAI_CODE
if (isTestnet) {
conversionRate = 0
} else if (isDai) {
conversionRate = 1

View File

@ -12,6 +12,7 @@ const validUrl = require('valid-url')
const exportAsFile = require('./util').exportAsFile
const Modal = require('../../ui/app/components/modals/index').Modal
const ethNetProps = require('eth-net-props')
const { networks } = require('../../app/scripts/controllers/network/util')
module.exports = connect(mapStateToProps)(ConfigScreen)
@ -290,46 +291,12 @@ function currentProviderDisplay (metamaskState, state) {
const provider = metamaskState.provider
let title, value
switch (provider.type) {
case 'mainnet':
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(1)
break
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
if (networks[provider.type]) {
title = 'Current Network'
value = ethNetProps.props.getNetworkDisplayName(networks[provider.type].networkID)
} else {
title = 'Current RPC'
value = metamaskState.provider.rpcTarget
}
return h('div', [

View File

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

6
package-lock.json generated
View File

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

View File

@ -118,7 +118,7 @@
"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-method-registry": "^1.0.0",
"eth-net-props": "^1.0.10",
"eth-net-props": "^1.0.11",
"eth-phishing-detect": "^1.1.4",
"eth-query": "^2.1.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.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'),
tokens: {
menu: By.id('wallet-view__tab-tokens'),
@ -322,6 +323,7 @@ module.exports = {
},
buyEther: {
title: By.className('flex-center buy-title'),
buttonArrow: By.className('fa fa-arrow-left fa-lg cursor-pointer'),
},
info: {
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')
})
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)
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')
})
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)
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)
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)
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')
})
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)
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)
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)
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)
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 () => {
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 () => {
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 () => {
@ -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 () => {
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')
})
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)
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')
})
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)
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)
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)
assert.equal(await f.assertTokensNotDisplayed(), true, 'tokens are displayed')
})

View File

@ -63,7 +63,7 @@ const customRPC = async (f) => {
await f.clearField(fieldRpc)
await fieldRpc.sendKeys(correctRpcUrl + 0)
await f.driver.findElement(screens.settings.buttonSave).click()
await f.delay(10000)
await f.delay(20000)
const customUrlElement = await f.waitUntilShowUp(screens.settings.currentNetwork)
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")
})
it("Button 'Buy Ether' is displayed", async () => {
it("Button 'Buy POA' is displayed", async function () {
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')
})
it("Open screen 'Buy Ether'", async () => {
it("Open screen 'Buy'", async function () {
const button = await f.waitUntilShowUp(screens.confirmTransaction.button.buyEther)
await button.click()
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)
await arrow.click()
})

View File

@ -4,7 +4,19 @@ const {
getCurrentKeyring,
ifLooseAcc,
ifContractAcc,
addressSummary,
isValidAddress,
numericBalance,
parseBalance,
formatBalance,
normalizeToWei,
normalizeEthStringToWei,
normalizeNumberToWei,
isHex,
} = 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', () => {
it('returns correct significant decimals', () => {
@ -74,3 +86,247 @@ describe('ifContractAcc(keyring) function', () => {
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 () {
var input = new ethUtil.BN(ethInWei, 10).toJSON()
console.log('input = ', input)
var result = util.formatBalance(input, 4)
assert.equal(result, '1.0000 ETH')
})
it('should return eth as string followed by ETH', function () {
var input = new ethUtil.BN(ethInWei, 10).div(new ethUtil.BN('2', 10)).toJSON()
console.log('input = ', input)
var result = util.formatBalance(input, 3)
assert.equal(result, '0.500 ETH')
})

View File

@ -11,6 +11,9 @@ const ethUtil = require('ethereumjs-util')
const { fetchLocale } = require('../i18n-helper')
const log = require('loglevel')
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 WebcamUtils = require('../lib/webcam-utils')
@ -2007,7 +2010,9 @@ function setProviderType (type) {
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) => {
if (err) {
log.error(err.stack)