From 13be683701bc46d8f1bcbaa301e2b7f01a34e29c Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 9 May 2019 14:57:14 -0230 Subject: New settings custom rpc form (#6490) * Add networks tab to settings, with header. * Adds network list to settings network tab. * Adds form to settings networks tab and connects it to network list. * Network tab: form adding and editing working * Settings network form properly handles input errors * Add translations for settings network form * Clean up styles of settings network tab. * Add popup-view styles and behaviour to settings network tab. * Fix save button on settings network form * Adds 'Add Network' button and addMode to settings networks tab * Lint fix for settings networks tab addition * Fix navigation in settings networks tab. * Editing an rpcurl in networks tab does not create new network, just changes rpc of old * Fix layout of settings tabs other than network * Networks dropdown 'Custom Rpc' item links to networks tab in settings. * Update settings sidebar networks subheader. * Make networks tab buttons width consistent with input widths in extension view. * Fix settings screen subheader height in popup view * Fix height of add networks button in popup view * Add optional label to chainId and symbol form labels in networks setting tab * Style fixes for networks tab headers * Add ability to customize block explorer used by custom rpc * Stylistic improvements+fixes to custom rpc form. * Hide cancel button. * Highlight and show network form of provider by default. * Standardize network subheader name to 'Networks' * Update e2e tests for new settings network form * Update unit tests for new rpcPrefs prop * Extract blockexplorer url construction into method. * Fix broken styles on non-network tabs in popup mode * Fix block explorer url links for cases when provider in state has not been updated. * Fix vertical spacing of network form * Don't allow click of save button on network form if nothing has changed * Ensure add network button is shown in popup view * Lint fix for networks tab * Fix block explorer url preference setting. * Fix e2e tests for custom blockexplorer in account details modal changes. * Update integration test states to include frequentRpcList property * Fix some capitalizations in en/messages.json * Remove some console.logs added during custom rpc form work * Fix external account link text and url for modal and dropdown. * Documentation, url validation, proptype required additions and lint fixes on network tab and form. --- .../app/dropdowns/account-details-dropdown.js | 17 +- .../components/app/dropdowns/network-dropdown.js | 10 +- .../components/app/modals/account-details-modal.js | 12 +- .../transaction-list-item-details.component.js | 15 +- .../transaction-list-item.component.js | 3 + .../transaction-list-item.container.js | 5 +- .../ui/text-field/text-field.component.js | 6 +- ui/app/ducks/app/app.js | 12 ++ ui/app/helpers/constants/routes.js | 2 + ui/app/helpers/utils/transactions.util.js | 16 ++ ui/app/pages/settings/index.scss | 36 +++- ui/app/pages/settings/networks-tab/index.js | 1 + ui/app/pages/settings/networks-tab/index.scss | 200 ++++++++++++++++++ .../settings/networks-tab/network-form/index.js | 1 + .../network-form/network-form.component.js | 225 +++++++++++++++++++++ .../networks-tab/networks-tab.component.js | 214 ++++++++++++++++++++ .../networks-tab/networks-tab.constants.js | 50 +++++ .../networks-tab/networks-tab.container.js | 77 +++++++ ui/app/pages/settings/settings.component.js | 10 +- ui/app/selectors/selectors.js | 8 + ui/app/store/actions.js | 48 ++++- ui/lib/account-link.js | 6 +- 22 files changed, 944 insertions(+), 30 deletions(-) create mode 100644 ui/app/pages/settings/networks-tab/index.js create mode 100644 ui/app/pages/settings/networks-tab/index.scss create mode 100644 ui/app/pages/settings/networks-tab/network-form/index.js create mode 100644 ui/app/pages/settings/networks-tab/network-form/network-form.component.js create mode 100644 ui/app/pages/settings/networks-tab/networks-tab.component.js create mode 100644 ui/app/pages/settings/networks-tab/networks-tab.constants.js create mode 100644 ui/app/pages/settings/networks-tab/networks-tab.container.js (limited to 'ui') diff --git a/ui/app/components/app/dropdowns/account-details-dropdown.js b/ui/app/components/app/dropdowns/account-details-dropdown.js index 3d4598946..cbeccdd81 100644 --- a/ui/app/components/app/dropdowns/account-details-dropdown.js +++ b/ui/app/components/app/dropdowns/account-details-dropdown.js @@ -4,7 +4,7 @@ const h = require('react-hyperscript') const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../../store/actions') -const { getSelectedIdentity } = require('../../../selectors/selectors') +const { getSelectedIdentity, getRpcPrefsForCurrentProvider } = require('../../../selectors/selectors') const genAccountLink = require('../../../../lib/account-link.js') const { Menu, Item, CloseArea } = require('./components/menu') @@ -20,6 +20,7 @@ function mapStateToProps (state) { selectedIdentity: getSelectedIdentity(state), network: state.metamask.network, keyrings: state.metamask.keyrings, + rpcPrefs: getRpcPrefsForCurrentProvider(state), } } @@ -28,8 +29,8 @@ function mapDispatchToProps (dispatch) { showAccountDetailModal: () => { dispatch(actions.showModal({ name: 'ACCOUNT_DETAILS' })) }, - viewOnEtherscan: (address, network) => { - global.platform.openWindow({ url: genAccountLink(address, network) }) + viewOnEtherscan: (address, network, rpcPrefs) => { + global.platform.openWindow({ url: genAccountLink(address, network, rpcPrefs) }) }, showRemoveAccountConfirmationModal: (identity) => { return dispatch(actions.showModal({ name: 'CONFIRM_REMOVE_ACCOUNT', identity })) @@ -56,7 +57,9 @@ AccountDetailsDropdown.prototype.render = function () { keyrings, showAccountDetailModal, viewOnEtherscan, - showRemoveAccountConfirmationModal } = this.props + showRemoveAccountConfirmationModal, + rpcPrefs, + } = this.props const address = selectedIdentity.address @@ -112,10 +115,12 @@ AccountDetailsDropdown.prototype.render = function () { name: 'Clicked View on Etherscan', }, }) - viewOnEtherscan(address, network) + viewOnEtherscan(address, network, rpcPrefs) this.props.onClose() }, - text: this.context.t('viewOnEtherscan'), + text: (rpcPrefs.blockExplorerUrl + ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1]]) + : this.context.t('viewOnEtherscan')), icon: h(`img`, { src: 'images/open-etherscan.svg', style: { height: '15px' } }), }), isRemovable ? h(Item, { diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index dbe3f1bc8..378ad3ba6 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -10,7 +10,7 @@ const Dropdown = require('./components/dropdown').Dropdown const DropdownMenuItem = require('./components/dropdown').DropdownMenuItem const NetworkDropdownIcon = require('./components/network-dropdown-icon') const R = require('ramda') -const { ADVANCED_ROUTE } = require('../../../helpers/constants/routes') +const { NETWORKS_ROUTE } = require('../../../helpers/constants/routes') // classes from nodes of the toggle element. const notToggleElementClassnames = [ @@ -49,6 +49,7 @@ function mapDispatchToProps (dispatch) { }, showNetworkDropdown: () => dispatch(actions.showNetworkDropdown()), hideNetworkDropdown: () => dispatch(actions.hideNetworkDropdown()), + setNetworksTabAddMode: isInAddMode => dispatch(actions.setNetworksTabAddMode(isInAddMode)), } } @@ -72,7 +73,7 @@ module.exports = compose( // TODO: specify default props and proptypes NetworkDropdown.prototype.render = function () { const props = this.props - const { provider: { type: providerType, rpcTarget: activeNetwork } } = props + const { provider: { type: providerType, rpcTarget: activeNetwork }, setNetworksTabAddMode } = props const rpcListDetail = props.frequentRpcListDetail const isOpen = this.props.networkDropdownOpen const dropdownMenuItemStyle = { @@ -255,7 +256,10 @@ NetworkDropdown.prototype.render = function () { DropdownMenuItem, { closeMenu: () => this.props.hideNetworkDropdown(), - onClick: () => this.props.history.push(ADVANCED_ROUTE), + onClick: () => { + setNetworksTabAddMode(true) + this.props.history.push(NETWORKS_ROUTE) + }, style: dropdownMenuItemStyle, }, [ diff --git a/ui/app/components/app/modals/account-details-modal.js b/ui/app/components/app/modals/account-details-modal.js index 1b1ca6b8e..6cffc918b 100644 --- a/ui/app/components/app/modals/account-details-modal.js +++ b/ui/app/components/app/modals/account-details-modal.js @@ -5,7 +5,7 @@ const inherits = require('util').inherits const connect = require('react-redux').connect const actions = require('../../../store/actions') const AccountModalContainer = require('./account-modal-container') -const { getSelectedIdentity } = require('../../../selectors/selectors') +const { getSelectedIdentity, getRpcPrefsForCurrentProvider } = require('../../../selectors/selectors') const genAccountLink = require('../../../../lib/account-link.js') const QrView = require('../../ui/qr-code') const EditableLabel = require('../../ui/editable-label') @@ -17,6 +17,7 @@ function mapStateToProps (state) { network: state.metamask.network, selectedIdentity: getSelectedIdentity(state), keyrings: state.metamask.keyrings, + rpcPrefs: getRpcPrefsForCurrentProvider(state), } } @@ -54,6 +55,7 @@ AccountDetailsModal.prototype.render = function () { showExportPrivateKeyModal, setAccountLabel, keyrings, + rpcPrefs, } = this.props const { name, address } = selectedIdentity @@ -86,8 +88,12 @@ AccountDetailsModal.prototype.render = function () { h(Button, { type: 'secondary', className: 'account-modal__button', - onClick: () => global.platform.openWindow({ url: genAccountLink(address, network) }), - }, this.context.t('etherscanView')), + onClick: () => { + global.platform.openWindow({ url: genAccountLink(address, network, rpcPrefs) }) + }, + }, (rpcPrefs.blockExplorerUrl + ? this.context.t('blockExplorerView', [rpcPrefs.blockExplorerUrl.match(/^https?:\/\/(.+)/)[1]]) + : this.context.t('viewOnEtherscan'))), // Holding on redesign for Export Private Key functionality diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js index 4a3b04998..72ca784e2 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -1,13 +1,15 @@ import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import copyToClipboard from 'copy-to-clipboard' +import { + getBlockExplorerUrlForTx, +} from '../../../helpers/utils/transactions.util' import SenderToRecipient from '../../ui/sender-to-recipient' import { FLAT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants' import TransactionActivityLog from '../transaction-activity-log' import TransactionBreakdown from '../transaction-breakdown' import Button from '../../ui/button' import Tooltip from '../../ui/tooltip' -import prefixForNetwork from '../../../../lib/etherscan-prefix-for-network' export default class TransactionListItemDetails extends PureComponent { static contextTypes = { @@ -22,6 +24,7 @@ export default class TransactionListItemDetails extends PureComponent { showRetry: PropTypes.bool, cancelDisabled: PropTypes.bool, transactionGroup: PropTypes.object, + rpcPrefs: PropTypes.object, } state = { @@ -30,12 +33,9 @@ export default class TransactionListItemDetails extends PureComponent { } handleEtherscanClick = () => { - const { transactionGroup: { primaryTransaction } } = this.props + const { transactionGroup: { primaryTransaction }, rpcPrefs } = this.props const { hash, metamaskNetworkId } = primaryTransaction - const prefix = prefixForNetwork(metamaskNetworkId) - const etherscanUrl = `https://${prefix}etherscan.io/tx/${hash}` - this.context.metricsEvent({ eventOpts: { category: 'Navigation', @@ -44,7 +44,7 @@ export default class TransactionListItemDetails extends PureComponent { }, }) - global.platform.openWindow({ url: etherscanUrl }) + global.platform.openWindow({ url: getBlockExplorerUrlForTx(metamaskNetworkId, hash, rpcPrefs) }) } handleCancel = event => { @@ -125,6 +125,7 @@ export default class TransactionListItemDetails extends PureComponent { showRetry, onCancel, onRetry, + rpcPrefs: { blockExplorerUrl } = {}, } = this.props const { primaryTransaction: transaction } = transactionGroup const { txParams: { to, from } = {} } = transaction @@ -158,7 +159,7 @@ export default class TransactionListItemDetails extends PureComponent { /> - + + + + ) + } + + renderNetworkListItem (network, selectRpcUrl) { + const { + setSelectedSettingsRpcUrl, + setNetworksTabAddMode, + networkIsSelected, + providerUrl, + providerType, + networksTabIsInAddMode, + } = this.props + const { + border, + iconColor, + label, + labelKey, + rpcUrl, + providerType: currentProviderType, + } = network + + const listItemNetworkIsSelected = selectRpcUrl && selectRpcUrl === rpcUrl + const listItemUrlIsProviderUrl = rpcUrl === providerUrl + const listItemTypeIsProviderNonRpcType = providerType !== 'rpc' && currentProviderType === providerType + const listItemNetworkIsCurrentProvider = !networkIsSelected && !networksTabIsInAddMode && (listItemUrlIsProviderUrl || listItemTypeIsProviderNonRpcType) + const displayNetworkListItemAsSelected = listItemNetworkIsSelected || listItemNetworkIsCurrentProvider + + return ( +
{ + setNetworksTabAddMode(false) + setSelectedSettingsRpcUrl(rpcUrl) + }} + > + +
+ { label || this.context.t(labelKey) } +
+
+
+ ) + } + + renderNetworksList () { + const { networksToRender, selectedNetwork, networkIsSelected, networksTabIsInAddMode, networkDefaultedToProvider } = this.props + + return ( +
+ { networksToRender.map(network => this.renderNetworkListItem(network, selectedNetwork.rpcUrl)) } +
+ ) + } + + renderNetworksTabContent () { + const { + setRpcTarget, + setSelectedSettingsRpcUrl, + setNetworksTabAddMode, + selectedNetwork: { + labelKey, + label, + rpcUrl, + chainId, + ticker, + viewOnly, + rpcPrefs, + blockExplorerUrl, + }, + networksTabIsInAddMode, + editRpc, + networkDefaultedToProvider, + } = this.props + const envIsPopup = getEnvironmentType() === ENVIRONMENT_TYPE_POPUP + + return ( +
+ {this.renderNetworksList()} + {networksTabIsInAddMode || !envIsPopup || (envIsPopup && !networkDefaultedToProvider) + ? { + setNetworksTabAddMode(false) + setSelectedSettingsRpcUrl(null) + }} + viewOnly={viewOnly} + networksTabIsInAddMode={networksTabIsInAddMode} + rpcPrefs={rpcPrefs} + blockExplorerUrl={blockExplorerUrl} + /> + : null + } +
+ ) + } + + renderContent () { + const { setNetworksTabAddMode, setSelectedSettingsRpcUrl, networkIsSelected, networksTabIsInAddMode } = this.props + + return ( +
+ {this.renderSubHeader()} + {this.renderNetworksTabContent()} + {!networkIsSelected && !networksTabIsInAddMode + ?
+ +
+ : null + } +
+ ) + } + + render () { + return this.renderContent() + } +} diff --git a/ui/app/pages/settings/networks-tab/networks-tab.constants.js b/ui/app/pages/settings/networks-tab/networks-tab.constants.js new file mode 100644 index 000000000..d3d1a01cc --- /dev/null +++ b/ui/app/pages/settings/networks-tab/networks-tab.constants.js @@ -0,0 +1,50 @@ +const defaultNetworksData = [ + { + labelKey: 'mainnet', + iconColor: '#29B6AF', + providerType: 'mainnet', + rpcUrl: 'https://api.infura.io/v1/jsonrpc/mainnet', + chainId: '1', + ticker: 'ETH', + blockExplorerUrl: 'https://etherscan.io', + }, + { + labelKey: 'ropsten', + iconColor: '#FF4A8D', + providerType: 'ropsten', + rpcUrl: 'https://api.infura.io/v1/jsonrpc/ropsten', + chainId: '3', + ticker: 'ETH', + blockExplorerUrl: 'https://ropsten.etherscan.io', + }, + { + labelKey: 'kovan', + iconColor: '#9064FF', + providerType: 'kovan', + rpcUrl: 'https://api.infura.io/v1/jsonrpc/kovan', + chainId: '4', + ticker: 'ETH', + blockExplorerUrl: 'https://etherscan.io', + }, + { + labelKey: 'rinkeby', + iconColor: '#F6C343', + providerType: 'rinkeby', + rpcUrl: 'https://api.infura.io/v1/jsonrpc/rinkeby', + chainId: '42', + ticker: 'ETH', + blockExplorerUrl: 'https://rinkeby.etherscan.io', + }, + { + labelKey: 'localhost', + iconColor: 'white', + border: '1px solid #6A737D', + providerType: 'localhost', + rpcUrl: 'http://localhost:8545/', + blockExplorerUrl: 'https://etherscan.io', + }, +] + +export { + defaultNetworksData, +} diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js new file mode 100644 index 000000000..a5d71f714 --- /dev/null +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -0,0 +1,77 @@ +import NetworksTab from './networks-tab.component' +import { compose } from 'recompose' +import { connect } from 'react-redux' +import { withRouter } from 'react-router-dom' +import { + setSelectedSettingsRpcUrl, + updateAndSetCustomRpc, + displayWarning, + setNetworksTabAddMode, + editRpc, +} from '../../../store/actions' +import { defaultNetworksData } from './networks-tab.constants' +const defaultNetworks = defaultNetworksData.map(network => ({ ...network, viewOnly: true })) + +const mapStateToProps = state => { + const { + frequentRpcListDetail, + provider, + } = state.metamask + const { + networksTabSelectedRpcUrl, + networksTabIsInAddMode, + } = state.appState + + const frequentRpcNetworkListDetails = frequentRpcListDetail.map(rpc => { + return { + label: rpc.nickname, + iconColor: '#6A737D', + providerType: 'rpc', + rpcUrl: rpc.rpcUrl, + chainId: rpc.chainId, + ticker: rpc.ticker, + blockExplorerUrl: rpc.rpcPrefs && rpc.rpcPrefs.blockExplorerUrl || '', + } + }) + + const networksToRender = [ ...defaultNetworks, ...frequentRpcNetworkListDetails ] + let selectedNetwork = networksToRender.find(network => network.rpcUrl === networksTabSelectedRpcUrl) || {} + const networkIsSelected = Boolean(selectedNetwork.rpcUrl) + + let networkDefaultedToProvider = false + if (!networkIsSelected && !networksTabIsInAddMode) { + selectedNetwork = networksToRender.find(network => { + return network.rpcUrl === provider.rpcTarget || network.providerType !== 'rpc' && network.providerType === provider.type + }) || {} + networkDefaultedToProvider = true + } + + return { + selectedNetwork, + networksToRender, + networkIsSelected, + networksTabIsInAddMode, + providerType: provider.type, + providerUrl: provider.rpcTarget, + networkDefaultedToProvider, + } +} + +const mapDispatchToProps = dispatch => { + return { + setSelectedSettingsRpcUrl: newRpcUrl => dispatch(setSelectedSettingsRpcUrl(newRpcUrl)), + setRpcTarget: (newRpc, chainId, ticker, nickname, rpcPrefs) => { + dispatch(updateAndSetCustomRpc(newRpc, chainId, ticker, nickname, rpcPrefs)) + }, + displayWarning: warning => dispatch(displayWarning(warning)), + setNetworksTabAddMode: isInAddMode => dispatch(setNetworksTabAddMode(isInAddMode)), + editRpc: (oldRpc, newRpc, chainId, ticker, nickname, rpcPrefs) => { + dispatch(editRpc(oldRpc, newRpc, chainId, ticker, nickname, rpcPrefs)) + }, + } +} + +export default compose( + withRouter, + connect(mapStateToProps, mapDispatchToProps) +)(NetworksTab) diff --git a/ui/app/pages/settings/settings.component.js b/ui/app/pages/settings/settings.component.js index fe799a6e8..a2f137264 100644 --- a/ui/app/pages/settings/settings.component.js +++ b/ui/app/pages/settings/settings.component.js @@ -6,6 +6,7 @@ import { getEnvironmentType } from '../../../../app/scripts/lib/util' import TabBar from '../../components/app/tab-bar' import c from 'classnames' import SettingsTab from './settings-tab' +import NetworksTab from './networks-tab' import AdvancedTab from './advanced-tab' import InfoTab from './info-tab' import SecurityTab from './security-tab' @@ -16,6 +17,7 @@ import { GENERAL_ROUTE, ABOUT_US_ROUTE, SETTINGS_ROUTE, + NETWORKS_ROUTE, } from '../../helpers/constants/routes' const ROUTES_TO_I18N_KEYS = { @@ -55,7 +57,7 @@ class SettingsPage extends PureComponent { >
{ - !this.isCurrentPath(SETTINGS_ROUTE) && ( + !this.isCurrentPath(SETTINGS_ROUTE) && !this.isCurrentPath(NETWORKS_ROUTE) && (
history.push(SETTINGS_ROUTE)} @@ -104,6 +106,7 @@ class SettingsPage extends PureComponent { { content: t('general'), description: t('generalSettingsDescription'), key: GENERAL_ROUTE }, { content: t('advanced'), description: t('advancedSettingsDescription'), key: ADVANCED_ROUTE }, { content: t('securityAndPrivacy'), description: t('securitySettingsDescription'), key: SECURITY_ROUTE }, + { content: t('networks'), description: t('networkSettingsDescription'), key: NETWORKS_ROUTE }, { content: t('about'), description: t('aboutSettingsDescription'), key: ABOUT_US_ROUTE }, ]} isActive={key => { @@ -135,6 +138,11 @@ class SettingsPage extends PureComponent { path={ADVANCED_ROUTE} component={AdvancedTab} /> + rpcInfo.rpcUrl === provider.rpcTarget) + const { rpcPrefs = {} } = selectRpcInfo || {} + return rpcPrefs +} diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 95c6dbb77..7d45f0932 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -239,6 +239,7 @@ var actions = { updateAndSetCustomRpc: updateAndSetCustomRpc, setRpcTarget: setRpcTarget, delRpcTarget: delRpcTarget, + editRpc: editRpc, setProviderType: setProviderType, SET_HARDWARE_WALLET_DEFAULT_HD_PATH: 'SET_HARDWARE_WALLET_DEFAULT_HD_PATH', setHardwareWalletDefaultHdPath, @@ -350,6 +351,11 @@ var actions = { setFirstTimeFlowType, SET_FIRST_TIME_FLOW_TYPE: 'SET_FIRST_TIME_FLOW_TYPE', + + SET_SELECTED_SETTINGS_RPC_URL: 'SET_SELECTED_SETTINGS_RPC_URL', + setSelectedSettingsRpcUrl, + SET_NETWORKS_TAB_ADD_MODE: 'SET_NETWORKS_TAB_ADD_MODE', + setNetworksTabAddMode, } module.exports = actions @@ -1958,10 +1964,10 @@ function setPreviousProvider (type) { } } -function updateAndSetCustomRpc (newRpc, chainId, ticker = 'ETH', nickname) { +function updateAndSetCustomRpc (newRpc, chainId, ticker = 'ETH', nickname, rpcPrefs) { return (dispatch) => { log.debug(`background.updateAndSetCustomRpc: ${newRpc} ${chainId} ${ticker} ${nickname}`) - background.updateAndSetCustomRpc(newRpc, chainId, ticker, nickname || newRpc, (err) => { + background.updateAndSetCustomRpc(newRpc, chainId, ticker, nickname || newRpc, rpcPrefs, (err) => { if (err) { log.error(err) return dispatch(actions.displayWarning('Had a problem changing networks!')) @@ -1974,6 +1980,29 @@ function updateAndSetCustomRpc (newRpc, chainId, ticker = 'ETH', nickname) { } } +function editRpc (oldRpc, newRpc, chainId, ticker = 'ETH', nickname, rpcPrefs) { + return (dispatch) => { + log.debug(`background.delRpcTarget: ${oldRpc}`) + background.delCustomRpc(oldRpc, (err) => { + if (err) { + log.error(err) + return dispatch(self.displayWarning('Had a problem removing network!')) + } + dispatch(actions.setSelectedToken()) + background.updateAndSetCustomRpc(newRpc, chainId, ticker, nickname || newRpc, rpcPrefs, (err) => { + if (err) { + log.error(err) + return dispatch(actions.displayWarning('Had a problem changing networks!')) + } + dispatch({ + type: actions.SET_RPC_TARGET, + value: newRpc, + }) + }) + }) + } +} + function setRpcTarget (newRpc, chainId, ticker = 'ETH', nickname) { return (dispatch) => { log.debug(`background.setRpcTarget: ${newRpc} ${chainId} ${ticker} ${nickname}`) @@ -2000,6 +2029,7 @@ function delRpcTarget (oldRpc) { } } + // Calls the addressBookController to add a new address. function addToAddressBook (recipient, nickname = '') { log.debug(`background.addToAddressBook`) @@ -2716,3 +2746,17 @@ function setFirstTimeFlowType (type) { }) } } + +function setSelectedSettingsRpcUrl (newRpcUrl) { + return { + type: actions.SET_SELECTED_SETTINGS_RPC_URL, + value: newRpcUrl, + } +} + +function setNetworksTabAddMode (isInAddMode) { + return { + type: actions.SET_NETWORKS_TAB_ADD_MODE, + value: isInAddMode, + } +} diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js index 3eaa7cf71..f1428ba92 100644 --- a/ui/lib/account-link.js +++ b/ui/lib/account-link.js @@ -1,4 +1,8 @@ -module.exports = function (address, network) { +module.exports = function (address, network, rpcPrefs) { + if (rpcPrefs.blockExplorerUrl) { + return `${rpcPrefs.blockExplorerUrl}/address/${address}` + } + const net = parseInt(network) let link switch (net) { -- cgit v1.2.3