diff --git a/app/scripts/controllers/network/createLocalhostClient.js b/app/scripts/controllers/network/createLocalhostClient.js index 09b1d3c1c..3a435e5d0 100644 --- a/app/scripts/controllers/network/createLocalhostClient.js +++ b/app/scripts/controllers/network/createLocalhostClient.js @@ -2,9 +2,12 @@ const mergeMiddleware = require('json-rpc-engine/src/mergeMiddleware') const createFetchMiddleware = require('eth-json-rpc-middleware/fetch') const createBlockRefRewriteMiddleware = require('eth-json-rpc-middleware/block-ref-rewrite') const createBlockTrackerInspectorMiddleware = require('eth-json-rpc-middleware/block-tracker-inspector') +const createAsyncMiddleware = require('json-rpc-engine/src/createAsyncMiddleware') const providerFromMiddleware = require('eth-json-rpc-middleware/providerFromMiddleware') const BlockTracker = require('eth-block-tracker') +const inTest = process.env.IN_TEST === 'true' + module.exports = createLocalhostClient function createLocalhostClient () { @@ -13,9 +16,24 @@ function createLocalhostClient () { const blockTracker = new BlockTracker({ provider: blockProvider, pollingInterval: 1000 }) const networkMiddleware = mergeMiddleware([ + createEstimateGasMiddleware(), createBlockRefRewriteMiddleware({ blockTracker }), createBlockTrackerInspectorMiddleware({ blockTracker }), fetchMiddleware, ]) return { networkMiddleware, blockTracker } } + +function delay (time) { + return new Promise(resolve => setTimeout(resolve, time)) +} + + +function createEstimateGasMiddleware () { + return createAsyncMiddleware(async (req, _, next) => { + if (req.method === 'eth_estimateGas' && inTest) { + await delay(2000) + } + return next() + }) +} diff --git a/app/scripts/controllers/network/createPocketClient.js b/app/scripts/controllers/network/createPocketClient.js index bc0de2479..51836c547 100644 --- a/app/scripts/controllers/network/createPocketClient.js +++ b/app/scripts/controllers/network/createPocketClient.js @@ -102,7 +102,7 @@ function getNetworkIds ({ network }) { ticker = POA_TICK break case POA_SOKOL: - netId= POA_SOKOL_CODE.toString() + netId = POA_SOKOL_CODE.toString() chainId = POA_SOKOL_CHAINID ticker = POA_TICK break @@ -110,7 +110,7 @@ function getNetworkIds ({ network }) { throw new Error(`createPocketClient - unknown network "${network}"`) } return { - chainId, netId, ticker + chainId, netId, ticker, } } diff --git a/app/scripts/controllers/network/enums.js b/app/scripts/controllers/network/enums.js index f8c6184bd..1b340afa3 100644 --- a/app/scripts/controllers/network/enums.js +++ b/app/scripts/controllers/network/enums.js @@ -11,17 +11,17 @@ const RSK = 'rsk' const RSK_TESTNET = 'rsk_testnet' const LOCALHOST = 'localhost' -const ETH_TICK = "ETH" -const POA_TICK = "POA" +const ETH_TICK = 'ETH' +const POA_TICK = 'POA' -const MAINNET_CHAINID = "0X01" -const ROPSTEN_CHAINID = "0x03" -const RINKEBY_CHAINID = "0x04" -const KOVAN_CHAINID = "0x2a" -const GOERLI_TESTNET_CHAINID = "0X5" -const POA_CHAINID = "0x63" -const DAI_CHAINID = "0x64" -const POA_SOKOL_CHAINID = "0x4D" +const MAINNET_CHAINID = '0X01' +const ROPSTEN_CHAINID = '0x03' +const RINKEBY_CHAINID = '0x04' +const KOVAN_CHAINID = '0x2a' +const GOERLI_TESTNET_CHAINID = '0X5' +const POA_CHAINID = '0x63' +const DAI_CHAINID = '0x64' +const POA_SOKOL_CHAINID = '0x4D' const POA_CODE = 99 const DAI_CODE = 100 diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 3613202f5..beaee48df 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -14,6 +14,9 @@ const createPocketClient = require('./createPocketClient') const { createSwappableProxy, createEventEmitterProxy } = require('swappable-obj-proxy') const ethNetProps = require('eth-net-props') const parse = require('url-parse') +const extend = require('extend') +const networks = { networkList: {} } +const { isKnownProvider } = require('../../../../old-ui/app/util') const { ROPSTEN, @@ -43,8 +46,21 @@ const env = process.env.METAMASK_ENV const METAMASK_DEBUG = process.env.METAMASK_DEBUG const testMode = (METAMASK_DEBUG || env === 'test') +let defaultProviderConfigType +if (process.env.IN_TEST === 'true') { + defaultProviderConfigType = LOCALHOST +} else if (testMode) { + defaultProviderConfigType = POA_SOKOL +} else { + defaultProviderConfigType = POA +} + const defaultProviderConfig = { - type: testMode ? POA_SOKOL : POA, + type: defaultProviderConfigType, +} + +const defaultNetworkConfig = { + ticker: 'POA', } module.exports = class NetworkController extends EventEmitter { @@ -58,6 +74,7 @@ module.exports = class NetworkController extends EventEmitter { this.providerStore = new ObservableStore(providerConfig) this.networkStore = new ObservableStore('loading') this.dProviderStore = new ObservableStore({dProvider: false}) + this.networkConfig = new ObservableStore(defaultNetworkConfig) this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore, dProviderStore: this.dProviderStore }) this.on('networkDidChange', this.lookupNetwork) // provider and block tracker @@ -70,8 +87,8 @@ module.exports = class NetworkController extends EventEmitter { initializeProvider (providerParams) { this._baseProviderParams = providerParams - const { type, rpcTarget } = this.providerStore.getState() - this._configureProvider({ type, rpcTarget }) + const { type, rpcTarget, chainId, ticker, nickname } = this.providerStore.getState() + this._configureProvider({ type, rpcTarget, chainId, ticker, nickname }) this.lookupNetwork() } @@ -91,7 +108,20 @@ module.exports = class NetworkController extends EventEmitter { return this.networkStore.getState() } - setNetworkState (network) { + getNetworkConfig () { + return this.networkConfig.getState() + } + + setNetworkState (network, type) { + if (network === 'loading') { + return this.networkStore.putState(network) + } + + // type must be defined + if (!type) { + return + } + network = networks.networkList[type] && networks.networkList[type].chainId ? networks.networkList[type].chainId : network return this.networkStore.putState(network) } @@ -100,45 +130,46 @@ module.exports = class NetworkController extends EventEmitter { } lookupNetwork () { - const { type, rpcTarget } = this.providerStore.getState() // Prevent firing when provider is not defined. if (!this._provider) { return log.warn('NetworkController - lookupNetwork aborted due to missing provider') } + const { type, rpcTarget } = this.providerStore.getState() const ethQuery = new EthQuery(this._provider) + const initialNetwork = this.getNetworkState() ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { - if (err) return this.setNetworkState('loading') const targetHost = parse(rpcTarget, true).host const classicHost = parse(ethNetProps.RPCEndpoints(CLASSIC_CODE)[0], true).host if (type === CLASSIC || targetHost === classicHost) { network = CLASSIC_CODE.toString() } // workaround to avoid Mainnet and Classic are having the same network ID - log.info('web3.getNetwork returned ' + network) - this.setNetworkState(network) + const currentNetwork = this.getNetworkState() + if (initialNetwork === currentNetwork) { + if (err) { + return this.setNetworkState('loading') + } + log.info('web3.getNetwork returned ' + network) + this.setNetworkState(network, type) + } }) } - setRpcTarget (rpcTarget) { + setRpcTarget (rpcTarget, chainId, ticker = 'ETH', nickname = '', rpcPrefs) { const providerConfig = { type: 'rpc', rpcTarget, + chainId, + ticker, + nickname, + rpcPrefs, } this.providerConfig = providerConfig } - async setProviderType (type) { + async setProviderType (type, rpcTarget = '', ticker = 'ETH', nickname = '') { 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 || - type === GOERLI_TESTNET || - type === CLASSIC || - type === RSK || - type === RSK_TESTNET - , `NetworkController - Unknown rpc type "${type}"`) - const providerConfig = { type } + assert(isKnownProvider(type), `NetworkController - Unknown rpc type "${type}"`) + const providerConfig = { type, rpcTarget, ticker, nickname } this.providerConfig = providerConfig } @@ -155,11 +186,11 @@ module.exports = class NetworkController extends EventEmitter { return this.providerStore.getState() } - getDProvider(){ + getDProvider () { return this.dProviderStore.getState().dProvider } - setDProvider(key){ + setDProvider (key) { this.dProviderStore.updateState({ dProvider: key, }) @@ -172,46 +203,46 @@ module.exports = class NetworkController extends EventEmitter { _switchNetwork (opts) { this.setNetworkState('loading') this._configureProvider(opts) - this.emit('networkDidChange') + this.emit('networkDidChange', opts.type) } _configureProvider (opts) { - const { type, rpcTarget } = opts + const { type, rpcTarget, chainId, ticker, nickname } = opts // infura type-based endpoints const isInfura = INFURA_PROVIDER_TYPES.includes(type) // pocket type-based endpointes const isPocket = POCKET_PROVIDER_TYPES.includes(type) - if (!isPocket && this.dProviderStore.getState().dProvider){ + if (!isPocket && this.dProviderStore.getState().dProvider) { this.dProviderStore.updateState({ - dProvider: false + dProvider: false, }) } - if (isPocket && this.dProviderStore.getState().dProvider){ + if (isPocket && this.dProviderStore.getState().dProvider) { this._configurePocketProvider(opts) } else if (isInfura) { this._configureInfuraProvider(opts) // other type-based rpc endpoints } else if (type === POA) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_CODE)[0], chainId, ticker, nickname }) } else if (type === DAI) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(DAI_CODE)[0], chainId, ticker, nickname }) } else if (type === POA_SOKOL) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(POA_SOKOL_CODE)[0], chainId, ticker, nickname }) } else if (type === GOERLI_TESTNET) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(GOERLI_TESTNET_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(GOERLI_TESTNET_CODE)[0], chainId, ticker, nickname }) } else if (type === CLASSIC) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CLASSIC_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(CLASSIC_CODE)[0], chainId, ticker, nickname }) } else if (type === RSK) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_CODE)[0], chainId, ticker, nickname }) } else if (type === RSK_TESTNET) { - this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0] }) + this._configureStandardProvider({ rpcUrl: ethNetProps.RPCEndpoints(RSK_TESTNET_CODE)[0], chainId, ticker, nickname }) } else if (type === LOCALHOST) { this._configureLocalhostProvider() // url-based rpc endpoints } else if (type === 'rpc') { - this._configureStandardProvider({ rpcUrl: rpcTarget }) + this._configureStandardProvider({ rpcUrl: rpcTarget, chainId, ticker, nickname }) } else { throw new Error(`NetworkController - _configureProvider - unknown type "${type}"`) } @@ -221,6 +252,11 @@ module.exports = class NetworkController extends EventEmitter { log.info('NetworkController - configureInfuraProvider', type) const networkClient = createInfuraClient({ network: type }) this._setNetworkClient(networkClient) + // setup networkConfig + var settings = { + ticker: 'ETH', + } + this.networkConfig.putState(settings) } _configurePocketProvider ({ type }) { @@ -235,9 +271,22 @@ module.exports = class NetworkController extends EventEmitter { this._setNetworkClient(networkClient) } - _configureStandardProvider ({ rpcUrl }) { + _configureStandardProvider ({ rpcUrl, chainId, ticker, nickname }) { log.info('NetworkController - configureStandardProvider', rpcUrl) const networkClient = createJsonRpcClient({ rpcUrl }) + // hack to add a 'rpc' network with chainId + networks.networkList['rpc'] = { + chainId: chainId, + rpcUrl, + ticker: ticker || 'ETH', + nickname, + } + // setup networkConfig + var settings = { + network: chainId, + } + settings = extend(settings, networks.networkList['rpc']) + this.networkConfig.putState(settings) this._setNetworkClient(networkClient) } diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index d270f6f44..0cc2791b4 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -3,6 +3,8 @@ const extend = require('xtend') const EthQuery = require('eth-query') const log = require('loglevel') const pify = require('pify') +const { isKnownProvider, ifRSKByProviderType } = require('../../../old-ui/app/util') + class RecentBlocksController { @@ -24,26 +26,58 @@ class RecentBlocksController { * */ constructor (opts = {}) { - const { blockTracker, provider } = opts + const { blockTracker, provider, networkController } = opts + const { type } = networkController.getProviderConfig() this.blockTracker = blockTracker this.ethQuery = new EthQuery(provider) - this.historyLength = opts.historyLength || 40 + this.setHistoryLength(type, opts) const initState = extend({ recentBlocks: [], }, opts.initState) this.store = new ObservableStore(initState) - - this.blockTracker.on('latest', async (newBlockNumberHex) => { + const blockListner = async (newBlockNumberHex) => { try { await this.processBlock(newBlockNumberHex) } catch (err) { log.error(err) } + } + let isListening = false + + if (!isKnownProvider(type) && type !== 'loading') { + this.blockTracker.on('latest', blockListner) + isListening = true + } + networkController.on('networkDidChange', (newType) => { + this.setHistoryLength(newType, opts) + this.resetState() + this.backfill() + if (isKnownProvider(newType) && isListening) { + this.blockTracker.removeListener('latest', blockListner) + } else if ( + !isKnownProvider(type) && + type !== 'loading' && + !isListening + ) { + this.blockTracker.on('latest', blockListner) + } }) this.backfill() } + /** + * Sets historyLength param + * + */ + setHistoryLength (type, opts) { + if (ifRSKByProviderType(type)) { + this.historyLength = 1 + } else { + this.historyLength = opts.historyLength || 40 + } + } + /** * Sets store.recentBlocks to an empty array * diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index bc3acbf27..ef11eee55 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -130,6 +130,7 @@ module.exports = class MetamaskController extends EventEmitter { this.recentBlocksController = new RecentBlocksController({ blockTracker: this.blockTracker, provider: this.provider, + networkController: this.networkController, }) // account tracker watches balances, nonces, and any code at their address. diff --git a/old-ui/app/components/app-bar/networks-menu.js b/old-ui/app/components/app-bar/networks-menu.js index 6cd5344a4..dcd5804cd 100644 --- a/old-ui/app/components/app-bar/networks-menu.js +++ b/old-ui/app/components/app-bar/networks-menu.js @@ -70,8 +70,8 @@ class NetworksMenu extends Component { key={'default'} closeMenu={() => this.props.updateNetworksMenuOpenState(!isOpen)} onClick={() => { - props.setRpcTarget('http://localhost:8545') - props.setProviderType(LOCALHOST) + props.setProviderType(LOCALHOST, LOCALHOST_RPC_URL) + props.setRpcTarget(LOCALHOST_RPC_URL) }} style={{ paddingLeft: '20px', diff --git a/old-ui/app/config.js b/old-ui/app/config.js index b0a898287..242f80ab6 100644 --- a/old-ui/app/config.js +++ b/old-ui/app/config.js @@ -31,12 +31,13 @@ class ConfigScreen extends Component { super(props) this.state = { loading: false, - dProvider: props.metamask.dProviderStore.dProvider + dProvider: props.metamask.dProviderStore.dProvider, } } static propTypes = { dispatch: PropTypes.func, + metamask: PropTypes.object, } render () { @@ -44,9 +45,9 @@ class ConfigScreen extends Component { const metamaskState = state.metamask const warning = state.warning - if(state.metamask.dProviderStore.dProvider != this.state.dProvider){ + if (state.metamask.dProviderStore.dProvider !== this.state.dProvider) { this.setState({ - dProvider: this.props.metamask.dProviderStore.dProvider + dProvider: this.props.metamask.dProviderStore.dProvider, }) } @@ -173,7 +174,31 @@ class ConfigScreen extends Component { }, 'Reveal Seed Words'), ]), - h('hr.horizontal-line'), + h('hr.horizontal-line', { + style: { + marginTop: '20px', + }, + }), + + h('p', { + style: { + fontFamily: 'Nunito Regular', + fontSize: '14px', + lineHeight: '18px', + }, + }, [ + 'Switch to Decentralized Provider (Pocket)', + ]), + + h('input', { + type: 'checkbox', + name: 'pocket-checkbox', + checked: this.state.dProvider, + onChange: (event) => { + event.preventDefault() + this.toggleProvider() + }, + }), h('p.config-title', `Provider`), @@ -234,23 +259,23 @@ class ConfigScreen extends Component { ) } - toggleProvider(){ + toggleProvider () { const isPocket = POCKET_PROVIDER_TYPES.includes(this.props.metamask.provider.type) - if (isPocket){ - if (!this.state.dProvider){ + if (isPocket) { + if (!this.state.dProvider) { this.props.dispatch(actions.setDProvider(true)) this.setState({ - dProvider: true + dProvider: true, }) } else { this.props.dispatch(actions.setDProvider(false)) this.setState({ - dProvider: false + dProvider: false, }) } this.props.dispatch(actions.setProviderType(this.props.metamask.provider.type)) } else { - alert("Pocket does not support this network, using centralized provider") + alert('Pocket does not support this network, using centralized provider') } } diff --git a/old-ui/app/util.js b/old-ui/app/util.js index 15c45c45a..cecbe2f5e 100644 --- a/old-ui/app/util.js +++ b/old-ui/app/util.js @@ -6,6 +6,18 @@ const { DAI_CODE, RSK_CODE, RSK_TESTNET_CODE, + ROPSTEN, + RINKEBY, + KOVAN, + MAINNET, + LOCALHOST, + POA_SOKOL, + POA, + DAI, + GOERLI_TESTNET, + CLASSIC, + RSK, + RSK_TESTNET, } = require('../../app/scripts/controllers/network/enums') var valueTable = { @@ -54,9 +66,12 @@ module.exports = { ifHardwareAcc, getAllKeyRingsAccounts, ifRSK, + ifRSKByProviderType, ifPOA, toChecksumAddress, isValidChecksumAddress, + isInfuraProvider, + isKnownProvider, } function valuesFor (obj) { @@ -391,6 +406,11 @@ function ifRSK (network) { return numericNet === RSK_CODE || numericNet === RSK_TESTNET_CODE } +function ifRSKByProviderType (type) { + if (!type) return false + return type === RSK || type === RSK_TESTNET +} + function ifPOA (network) { if (!network) return false const numericNet = isNaN(network) ? network : parseInt(network) @@ -424,3 +444,21 @@ function toChecksumAddress (network, address, chainId = null) { function isValidChecksumAddress (network, address) { return isValidAddress(address, network) && toChecksumAddress(network, address) === address } + +function isInfuraProvider (type) { + const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET] + return INFURA_PROVIDER_TYPES.includes(type) +} + +function isKnownProvider (type) { + const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET] + return INFURA_PROVIDER_TYPES.includes(type) || + type === LOCALHOST || + type === POA_SOKOL || + type === POA || + type === DAI || + type === GOERLI_TESTNET || + type === CLASSIC || + type === RSK || + type === RSK_TESTNET +} diff --git a/package-lock.json b/package-lock.json index 1477eb882..fa76122b0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2904,6 +2904,23 @@ "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", "dev": true }, + "@types/glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", + "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", + "dev": true, + "requires": { + "@types/events": "*", + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, "@types/node": { "version": "10.14.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.9.tgz", @@ -6820,16 +6837,69 @@ "dev": true }, "chromedriver": { - "version": "74.0.0", - "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-74.0.0.tgz", - "integrity": "sha512-xXgsq0l4gVTY9X5vuccOSVj/iEBm3Bf5MIwzSAASIRJagt4BlWw77SxQq1f4JAJ35/9Ys4NLMA/kWFbd7A/gfQ==", + "version": "76.0.0", + "resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-76.0.0.tgz", + "integrity": "sha512-jGyqs0N+lMo9iaNQxGKNPiLJWb2L9s2rwbRr1jJeQ37n6JQ1+5YMGviv/Fx5Z08vBWYbAvrKEzFsuYf8ppl+lw==", "dev": true, "requires": { - "del": "^3.0.0", + "del": "^4.1.1", "extract-zip": "^1.6.7", "mkdirp": "^0.5.1", "request": "^2.88.0", "tcp-port-used": "^1.0.1" + }, + "dependencies": { + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + } + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + } + }, + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + } } }, "ci-info": { @@ -38381,9 +38451,9 @@ "dev": true }, "selenium-webdriver": { - "version": "4.0.0-alpha.3", - "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.3.tgz", - "integrity": "sha512-78a8bbvVtl3asv5JAiBXvK4KQ+GmXBCMO0DU1ZMbdO9EAb+ydPA53CI4ZA+I8muSLSVgNhRAnsndNWZLIQN2LA==", + "version": "4.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/selenium-webdriver/-/selenium-webdriver-4.0.0-alpha.4.tgz", + "integrity": "sha512-etJt20d8qInkxMAHIm5SEpPBSS+CdxVcybnxzSIB/GlWErb8pIWrArz/VA6VfUW0/6tIcokepXQ5ufvdzqqk1A==", "dev": true, "requires": { "jszip": "^3.1.5", diff --git a/package.json b/package.json index 82e3334f7..8645fa98b 100644 --- a/package.json +++ b/package.json @@ -233,7 +233,7 @@ "brfs": "^1.6.1", "browserify": "^16.2.3", "chai": "^4.1.0", - "chromedriver": "^74.0.0", + "chromedriver": "^76.0.0", "clipboardy": "^1.2.3", "compression": "^1.7.1", "coveralls": "^3.0.0", @@ -308,7 +308,7 @@ "resolve-url-loader": "^2.3.0", "rimraf": "^2.6.2", "sass-loader": "^7.0.1", - "selenium-webdriver": "^4.0.0-alpha.1", + "selenium-webdriver": "^4.0.0-alpha.4", "shell-parallel": "^1.0.3", "sinon": "^5.0.0", "source-map": "^0.7.2", diff --git a/test/e2e/nw.spec.js b/test/e2e/nw.spec.js index 7f5b75512..e8b213ffd 100644 --- a/test/e2e/nw.spec.js +++ b/test/e2e/nw.spec.js @@ -1,6 +1,7 @@ const path = require('path') const Func = require('./func').Functions const account1 = '0x2E428ABd9313D256d64D1f69fe3929C3BE18fD1f' +const account1RSK = '0x2E428aBd9313D256d64D1f69fe3929c3Be18Fd1F' const account2 = '0xd7b7AFeCa35e32594e29504771aC847E2a803742' const testsFolder = './test-cases' const setup = require(`${testsFolder}/setup.spec`) @@ -117,7 +118,7 @@ describe('Metamask popup page', async function () { }) describe('RSK network tests', async () => { - await RSKNetworkTests(f, account1) + await RSKNetworkTests(f, account1RSK) }) describe('Check the filter of emitted events', async () => { @@ -137,7 +138,7 @@ describe('Metamask popup page', async function () { await addTokeFromSearch(f) }) - describe('Custom Rpc', async () => { + describe('Custom RPC', async () => { await customRPC(f) }) }) diff --git a/test/e2e/test-cases/RSK-network-tests.js b/test/e2e/test-cases/RSK-network-tests.js index fe0a0b0f8..16acb9eda 100644 --- a/test/e2e/test-cases/RSK-network-tests.js +++ b/test/e2e/test-cases/RSK-network-tests.js @@ -1,90 +1,90 @@ -// const assert = require('assert') -// const { screens, elements, NETWORKS } = require('../elements') +const assert = require('assert') +const { screens, elements, NETWORKS } = require('../elements') const RSKNetworkTests = async (f, account1) => { - // it('connects to RSK mainnet', async function () { - // await f.setProvider(NETWORKS.RSK) - // await f.delay(2000) - // }) + it('connects to RSK mainnet', async function () { + await f.setProvider(NETWORKS.RSK) + await f.delay(2000) + }) - // it('connects to RSK testnet', async function () { - // await f.setProvider(NETWORKS.RSK_TESTNET) - // await f.delay(2000) - // }) + it('connects to RSK testnet', async function () { + await f.setProvider(NETWORKS.RSK_TESTNET) + await f.delay(2000) + }) - // it('checks zero exchange rate for RSK testnet', async function () { - // const balanceField = await f.waitUntilShowUp(screens.main.balance) - // const balanceUSDField = await f.waitUntilShowUp(screens.main.balanceUSD) - // await f.delay(2000) - // const balance = await balanceField.getText() - // const balanceUSD = await balanceUSDField.getText() - // console.log('Balance = ' + parseFloat(balance)) - // console.log('balanceUSD = ' + parseFloat(balanceUSD)) - // assert.equal(parseFloat(balance) > 0.0001, true, 'Balance of account ' + account1 + ' is TOO LOW in RSK testnet !!! Please refill it!!!!') - // assert.equal(parseFloat(balanceUSD), 0, 'USD balance of account is not zero') - // }) + it('checks zero exchange rate for RSK testnet', async function () { + const balanceField = await f.waitUntilShowUp(screens.main.balance) + const balanceUSDField = await f.waitUntilShowUp(screens.main.balanceUSD) + await f.delay(2000) + const balance = await balanceField.getText() + const balanceUSD = await balanceUSDField.getText() + console.log('Balance = ' + parseFloat(balance)) + console.log('balanceUSD = ' + parseFloat(balanceUSD)) + assert.equal(parseFloat(balance) > 0.0001, true, 'Balance of account ' + account1 + ' is TOO LOW in RSK testnet !!! Please refill it!!!!') + assert.equal(parseFloat(balanceUSD), 0, 'USD balance of account is not zero') + }) - // it('opens RSK faucet', async function () { - // await f.waitUntilShowUp(screens.main.buttons.buyRSK) - // const buttons = await f.driver.findElements(screens.main.buttons.buyRSK) - // assert.equal(buttons.length, 1, 'main screen isn\'t displayed') - // const buyButton = buttons[0] - // const buyButtonText = await buyButton.getText() - // assert.equal(buyButtonText, 'Buy', 'button has incorrect name') - // await buyButton.click() - // await f.delay(2000) - // const title = await f.waitUntilShowUp(screens.buyEther.title) - // assert.equal(await title.getText(), 'Buy RBTC', "screen 'Buy RBTC' has incorrect title text") - // await f.waitUntilShowUp(screens.buyEther.faucetLinkRSK) - // const faucetButtons = await f.driver.findElements(screens.buyEther.faucetLinkRSK) - // assert.equal(faucetButtons.length, 1, 'there is no faucet button on the screen') - // const faucetLinkButton = faucetButtons[0] - // assert.equal(await faucetLinkButton.getText(), 'RSK Testnet Test Faucet', "screen 'Buy RSK' has incorrect name for faucet link") - // await faucetLinkButton.click() - // await f.delay(3000) - // const [tab0, tab1] = await f.driver.getAllWindowHandles() - // await f.driver.switchTo().window(tab1) - // const faucetLink = await f.driver.getCurrentUrl() - // assert.equal(faucetLink, 'https://faucet.testnet.rsk.co/', 'Incorrect faucet link for RSK network') - // await f.driver.close() - // await f.driver.switchTo().window(tab0) - // const arrow = await f.waitUntilShowUp(elements.buttonArrow) - // await arrow.click() - // await f.delay(2000) - // }) + it('opens RSK faucet', async function () { + await f.waitUntilShowUp(screens.main.buttons.buyRSK) + const buttons = await f.driver.findElements(screens.main.buttons.buyRSK) + assert.equal(buttons.length, 1, 'main screen isn\'t displayed') + const buyButton = buttons[0] + const buyButtonText = await buyButton.getText() + assert.equal(buyButtonText, 'Buy', 'button has incorrect name') + await buyButton.click() + await f.delay(2000) + const title = await f.waitUntilShowUp(screens.buyEther.title) + assert.equal(await title.getText(), 'Buy RBTC', "screen 'Buy RBTC' has incorrect title text") + await f.waitUntilShowUp(screens.buyEther.faucetLinkRSK) + const faucetButtons = await f.driver.findElements(screens.buyEther.faucetLinkRSK) + assert.equal(faucetButtons.length, 1, 'there is no faucet button on the screen') + const faucetLinkButton = faucetButtons[0] + assert.equal(await faucetLinkButton.getText(), 'RSK Testnet Test Faucet', "screen 'Buy RSK' has incorrect name for faucet link") + await faucetLinkButton.click() + await f.delay(3000) + const [tab0, tab1] = await f.driver.getAllWindowHandles() + await f.driver.switchTo().window(tab1) + const faucetLink = await f.driver.getCurrentUrl() + assert.equal(faucetLink, 'https://faucet.testnet.rsk.co/', 'Incorrect faucet link for RSK network') + await f.driver.close() + await f.driver.switchTo().window(tab0) + const arrow = await f.waitUntilShowUp(elements.buttonArrow) + await arrow.click() + await f.delay(2000) + }) - // it('opens send transaction screen', async function () { - // const sendButton = await f.waitUntilShowUp(screens.main.buttons.sendRSK) - // assert.equal(await sendButton.getText(), screens.main.buttons.sendText) - // await f.click(sendButton) - // }) + it('opens send transaction screen', async function () { + const sendButton = await f.waitUntilShowUp(screens.main.buttons.sendRSK) + assert.equal(await sendButton.getText(), screens.main.buttons.sendText) + await f.click(sendButton) + }) - // it('adds recipient address and amount', async function () { - // const sendTranscationScreen = await f.waitUntilShowUp(screens.sendTransaction.title) - // assert.equal(await sendTranscationScreen.getText(), screens.sendTransaction.titleText, 'Transaction screen has incorrect titlr') - // const inputAddress = await f.waitUntilShowUp(screens.sendTransaction.field.address) - // const inputAmmount = await f.waitUntilShowUp(screens.sendTransaction.field.amount) - // await inputAddress.sendKeys(account1) - // await f.clearField(inputAmmount) - // await inputAmmount.sendKeys('0.000001') - // const button = await f.waitUntilShowUp(screens.sendTransaction.buttonNext) - // assert.equal(await button.getText(), 'Next', 'button has incorrect name') - // await f.click(button) - // }) + it('adds recipient address and amount', async function () { + const sendTranscationScreen = await f.waitUntilShowUp(screens.sendTransaction.title) + assert.equal(await sendTranscationScreen.getText(), screens.sendTransaction.titleText, 'Transaction screen has incorrect titlr') + const inputAddress = await f.waitUntilShowUp(screens.sendTransaction.field.address) + const inputAmmount = await f.waitUntilShowUp(screens.sendTransaction.field.amount) + await inputAddress.sendKeys(account1) + await f.clearField(inputAmmount) + await inputAmmount.sendKeys('0.000001') + const button = await f.waitUntilShowUp(screens.sendTransaction.buttonNext) + assert.equal(await button.getText(), 'Next', 'button has incorrect name') + await f.click(button) + }) - // it('confirms transaction', async function () { - // const inputGasLimit = await f.waitUntilShowUp(screens.confirmTransaction.fields.gasLimit) - // await f.clearField(inputGasLimit) - // await inputGasLimit.sendKeys('21000') - // const button = await f.waitUntilShowUp(screens.confirmTransaction.button.submit) - // assert.equal(await button.getAttribute('value'), 'Submit', 'button has incorrect name') - // await f.click(button) - // }) + it('confirms transaction', async function () { + const inputGasLimit = await f.waitUntilShowUp(screens.confirmTransaction.fields.gasLimit) + await f.clearField(inputGasLimit) + await inputGasLimit.sendKeys('21000') + const button = await f.waitUntilShowUp(screens.confirmTransaction.button.submit) + assert.equal(await button.getAttribute('value'), 'Submit', 'button has incorrect name') + await f.click(button) + }) - // it('finds the transaction in the transactions list', async function () { - // const transactionAmount = await f.waitUntilShowUp(screens.main.transactionList) - // assert.equal(await transactionAmount.getText(), '<0.001') - // }) + it('finds the transaction in the transactions list', async function () { + const transactionAmount = await f.waitUntilShowUp(screens.main.transactionList) + assert.equal(await transactionAmount.getText(), '<0.001') + }) } module.exports = RSKNetworkTests diff --git a/test/unit/app/controllers/network-contoller-test.js b/test/unit/app/controllers/network-contoller-test.js index 746b0d07a..f90128de9 100644 --- a/test/unit/app/controllers/network-contoller-test.js +++ b/test/unit/app/controllers/network-contoller-test.js @@ -47,7 +47,7 @@ describe('# Network Controller', function () { describe('#setNetworkState', function () { it('should update the network', function () { - networkController.setNetworkState(1) + networkController.setNetworkState(1, 'mainnet') const networkState = networkController.getNetworkState() assert.equal(networkState, 1, 'network is 1') }) diff --git a/test/unit/old-ui/app/util.spec.js b/test/unit/old-ui/app/util.spec.js index 6ce8dd383..86e06119a 100644 --- a/test/unit/old-ui/app/util.spec.js +++ b/test/unit/old-ui/app/util.spec.js @@ -14,9 +14,12 @@ const { normalizeNumberToWei, isHex, ifRSK, + ifRSKByProviderType, ifPOA, toChecksumAddress, isValidChecksumAddress, + isInfuraProvider, + isKnownProvider, } = require('../../../../old-ui/app/util') const ethUtil = require('ethereumjs-util') let ethInWei = '1' @@ -336,30 +339,29 @@ describe('normalizing values', function () { describe('#ifRSK', function () { it('checks if this is RSK chain', function () { - var result1 = ifRSK(30) - assert(result1) - var result2 = ifRSK(31) - assert(result2) - var result3 = ifRSK(1) - assert(!result3) - var result4 = ifRSK() - assert(!result4) + assert(ifRSK(30)) + assert(ifRSK(31)) + assert(!ifRSK(1)) + assert(!ifRSK()) }) }) + describe('#ifRSKByProviderType', function () { + it('checks if this is RSK chain based on provider type', function () { + assert(ifRSKByProviderType('rsk')) + assert(ifRSKByProviderType('rsk_testnet')) + assert(!ifRSKByProviderType('mainnet')) + assert(!ifRSKByProviderType()) + }) + }) describe('#ifPOA', function () { it('checks if this is POA chain', function () { - var resultSokol = ifPOA(77) - assert(resultSokol) - var resultCore = ifPOA(99) - assert(resultCore) - var resultXDai = ifPOA(100) - assert(resultXDai) - var resultMainnet = ifPOA(1) - assert(!resultMainnet) - var result4 = ifPOA() - assert(!result4) + assert(ifPOA(77)) + assert(ifPOA(99)) + assert(ifPOA(100)) + assert(!ifPOA(1)) + assert(!ifPOA()) }) }) @@ -380,12 +382,36 @@ describe('normalizing values', function () { describe('#isValidChecksumAddress', function () { it('checks if is valid checksum address', function () { - var resultMainnet = isValidChecksumAddress('30', addrRSKMainnet) - assert(resultMainnet) - var resultTestnet = isValidChecksumAddress('31', addrRSKTestnet) - assert(resultTestnet) - var resultNotRSK = isValidChecksumAddress('1', addrETHMainnet) - assert(resultNotRSK) + assert(isValidChecksumAddress('30', addrRSKMainnet)) + assert(isValidChecksumAddress('31', addrRSKTestnet)) + assert(isValidChecksumAddress('1', addrETHMainnet)) + }) + }) + + describe('#isInfuraProvider', function () { + it('checks, that the given provider is Infura provider', function () { + assert(isInfuraProvider('kovan')) + assert(isInfuraProvider('ropsten')) + assert(isInfuraProvider('rinkeby')) + assert(isInfuraProvider('mainnet')) + assert(!isInfuraProvider('goerli_testnet')) + assert(!isInfuraProvider('sokol')) + assert(!isInfuraProvider('classic')) + assert(!isInfuraProvider('rsk')) + }) + }) + + describe('#isKnownProvider', function () { + it('checks, that the given provider is Infura provider', function () { + assert(isKnownProvider('kovan')) + assert(isKnownProvider('ropsten')) + assert(isKnownProvider('rinkeby')) + assert(isKnownProvider('mainnet')) + assert(isKnownProvider('goerli_testnet')) + assert(isKnownProvider('sokol')) + assert(isKnownProvider('classic')) + assert(isKnownProvider('rsk')) + assert(!isKnownProvider('unknown_network')) }) }) }) diff --git a/ui/app/reducers/metamask.js b/ui/app/reducers/metamask.js index 743f475ef..9d7394a69 100644 --- a/ui/app/reducers/metamask.js +++ b/ui/app/reducers/metamask.js @@ -355,7 +355,7 @@ function reduceMetamask (state, action) { case actions.SET_DPROVIDER: return extend(metamaskState, { dProviderStore: { - dProvider : action.value, + dProvider: action.value, }, })