use etherscan-link for account-link (#10590)

feature/default_network_editable
Brad Decker 4 years ago committed by GitHub
parent 38fe75b7d9
commit aa37e30c08
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      test/unit/lib/account-link.test.js
  2. 6
      ui/app/components/app/menu-bar/account-options-menu.js
  3. 5
      ui/app/components/app/menu-bar/tests/menu-bar.test.js
  4. 6
      ui/app/components/app/modals/account-details-modal/account-details-modal.component.js
  5. 3
      ui/app/components/app/modals/account-details-modal/account-details-modal.container.js
  6. 9
      ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js
  7. 7
      ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js
  8. 9
      ui/app/pages/create-account/connect-hardware/account-list.js
  9. 34
      ui/app/pages/create-account/connect-hardware/index.js
  10. 23
      ui/lib/account-link.js

@ -1,4 +1,8 @@
import assert from 'assert'; import assert from 'assert';
import {
MAINNET_CHAIN_ID,
ROPSTEN_CHAIN_ID,
} from '../../../shared/constants/network';
import getAccountLink from '../../../ui/lib/account-link'; import getAccountLink from '../../../ui/lib/account-link';
describe('Account link', function () { describe('Account link', function () {
@ -7,19 +11,19 @@ describe('Account link', function () {
const tests = [ const tests = [
{ {
expected: 'https://etherscan.io/address/0xabcd', expected: 'https://etherscan.io/address/0xabcd',
network: 1, chainId: MAINNET_CHAIN_ID,
address: '0xabcd', address: '0xabcd',
}, },
{ {
expected: 'https://ropsten.etherscan.io/address/0xdef0', expected: 'https://ropsten.etherscan.io/address/0xdef0',
network: 3, chainId: ROPSTEN_CHAIN_ID,
address: '0xdef0', address: '0xdef0',
rpcPrefs: {}, rpcPrefs: {},
}, },
{ {
// test handling of `blockExplorerUrl` for a custom RPC // test handling of `blockExplorerUrl` for a custom RPC
expected: 'https://block.explorer/address/0xabcd', expected: 'https://block.explorer/address/0xabcd',
network: 31, chainId: '0x21',
address: '0xabcd', address: '0xabcd',
rpcPrefs: { rpcPrefs: {
blockExplorerUrl: 'https://block.explorer', blockExplorerUrl: 'https://block.explorer',
@ -28,7 +32,7 @@ describe('Account link', function () {
{ {
// test handling of trailing `/` in `blockExplorerUrl` for a custom RPC // test handling of trailing `/` in `blockExplorerUrl` for a custom RPC
expected: 'https://another.block.explorer/address/0xdef0', expected: 'https://another.block.explorer/address/0xdef0',
network: 33, chainId: '0x1f',
address: '0xdef0', address: '0xdef0',
rpcPrefs: { rpcPrefs: {
blockExplorerUrl: 'https://another.block.explorer/', blockExplorerUrl: 'https://another.block.explorer/',
@ -36,8 +40,8 @@ describe('Account link', function () {
}, },
]; ];
tests.forEach(({ expected, address, network, rpcPrefs }) => { tests.forEach(({ expected, address, chainId, rpcPrefs }) => {
assert.equal(getAccountLink(address, network, rpcPrefs), expected); assert.equal(getAccountLink(address, chainId, rpcPrefs), expected);
}); });
}); });
}); });

@ -8,8 +8,8 @@ import { CONNECTED_ROUTE } from '../../../helpers/constants/routes';
import { Menu, MenuItem } from '../../ui/menu'; import { Menu, MenuItem } from '../../ui/menu';
import getAccountLink from '../../../../lib/account-link'; import getAccountLink from '../../../../lib/account-link';
import { import {
getCurrentChainId,
getCurrentKeyring, getCurrentKeyring,
getCurrentNetwork,
getRpcPrefsForCurrentProvider, getRpcPrefsForCurrentProvider,
getSelectedIdentity, getSelectedIdentity,
} from '../../../selectors'; } from '../../../selectors';
@ -52,7 +52,7 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
}); });
const keyring = useSelector(getCurrentKeyring); const keyring = useSelector(getCurrentKeyring);
const network = useSelector(getCurrentNetwork); const chainId = useSelector(getCurrentChainId);
const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider);
const selectedIdentity = useSelector(getSelectedIdentity); const selectedIdentity = useSelector(getSelectedIdentity);
@ -92,7 +92,7 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) {
onClick={() => { onClick={() => {
viewOnEtherscanEvent(); viewOnEtherscanEvent();
global.platform.openTab({ global.platform.openTab({
url: getAccountLink(address, network, rpcPrefs), url: getAccountLink(address, chainId, rpcPrefs),
}); });
onClose(); onClose();
}} }}

@ -4,11 +4,14 @@ import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store'; import configureStore from 'redux-mock-store';
import { mountWithRouter } from '../../../../../../test/lib/render-helpers'; import { mountWithRouter } from '../../../../../../test/lib/render-helpers';
import MenuBar from '..'; import MenuBar from '..';
import { ROPSTEN_CHAIN_ID } from '../../../../../../shared/constants/network';
const initState = { const initState = {
activeTab: {}, activeTab: {},
metamask: { metamask: {
network: '1', provider: {
chainId: ROPSTEN_CHAIN_ID,
},
selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc',
identities: { identities: {
'0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': {

@ -9,7 +9,7 @@ import Button from '../../../ui/button';
export default class AccountDetailsModal extends Component { export default class AccountDetailsModal extends Component {
static propTypes = { static propTypes = {
selectedIdentity: PropTypes.object, selectedIdentity: PropTypes.object,
network: PropTypes.string, chainId: PropTypes.string,
showExportPrivateKeyModal: PropTypes.func, showExportPrivateKeyModal: PropTypes.func,
setAccountLabel: PropTypes.func, setAccountLabel: PropTypes.func,
keyrings: PropTypes.array, keyrings: PropTypes.array,
@ -23,7 +23,7 @@ export default class AccountDetailsModal extends Component {
render() { render() {
const { const {
selectedIdentity, selectedIdentity,
network, chainId,
showExportPrivateKeyModal, showExportPrivateKeyModal,
setAccountLabel, setAccountLabel,
keyrings, keyrings,
@ -62,7 +62,7 @@ export default class AccountDetailsModal extends Component {
className="account-details-modal__button" className="account-details-modal__button"
onClick={() => { onClick={() => {
global.platform.openTab({ global.platform.openTab({
url: getAccountLink(address, network, rpcPrefs), url: getAccountLink(address, chainId, rpcPrefs),
}); });
}} }}
> >

@ -3,12 +3,13 @@ import { showModal, setAccountLabel } from '../../../../store/actions';
import { import {
getSelectedIdentity, getSelectedIdentity,
getRpcPrefsForCurrentProvider, getRpcPrefsForCurrentProvider,
getCurrentChainId,
} from '../../../../selectors'; } from '../../../../selectors';
import AccountDetailsModal from './account-details-modal.component'; import AccountDetailsModal from './account-details-modal.component';
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
network: state.metamask.network, chainId: getCurrentChainId(state),
selectedIdentity: getSelectedIdentity(state), selectedIdentity: getSelectedIdentity(state),
keyrings: state.metamask.keyrings, keyrings: state.metamask.keyrings,
rpcPrefs: getRpcPrefsForCurrentProvider(state), rpcPrefs: getRpcPrefsForCurrentProvider(state),

@ -10,7 +10,8 @@ export default class ConfirmRemoveAccount extends Component {
hideModal: PropTypes.func.isRequired, hideModal: PropTypes.func.isRequired,
removeAccount: PropTypes.func.isRequired, removeAccount: PropTypes.func.isRequired,
identity: PropTypes.object.isRequired, identity: PropTypes.object.isRequired,
network: PropTypes.string.isRequired, chainId: PropTypes.string.isRequired,
rpcPrefs: PropTypes.object.isRequired,
}; };
static contextTypes = { static contextTypes = {
@ -49,7 +50,11 @@ export default class ConfirmRemoveAccount extends Component {
<div className="confirm-remove-account__account__link"> <div className="confirm-remove-account__account__link">
<a <a
className="" className=""
href={getAccountLink(identity.address, this.props.network)} href={getAccountLink(
identity.address,
this.props.chainId,
this.props.rpcPrefs,
)}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
title={this.context.t('etherscanView')} title={this.context.t('etherscanView')}

@ -1,12 +1,17 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { compose } from 'redux'; import { compose } from 'redux';
import withModalProps from '../../../../helpers/higher-order-components/with-modal-props'; import withModalProps from '../../../../helpers/higher-order-components/with-modal-props';
import {
getCurrentChainId,
getRpcPrefsForCurrentProvider,
} from '../../../../selectors';
import { removeAccount } from '../../../../store/actions'; import { removeAccount } from '../../../../store/actions';
import ConfirmRemoveAccount from './confirm-remove-account.component'; import ConfirmRemoveAccount from './confirm-remove-account.component';
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
return { return {
network: state.metamask.network, chainId: getCurrentChainId(state),
rpcPrefs: getRpcPrefsForCurrentProvider(state),
}; };
}; };

@ -112,7 +112,11 @@ class AccountList extends Component {
</div> </div>
<a <a
className="hw-account-list__item__link" className="hw-account-list__item__link"
href={getAccountLink(account.address, this.props.network)} href={getAccountLink(
account.address,
this.props.chainId,
this.props.rpcPrefs,
)}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
title={this.context.t('etherscanView')} title={this.context.t('etherscanView')}
@ -211,7 +215,8 @@ AccountList.propTypes = {
onAccountChange: PropTypes.func.isRequired, onAccountChange: PropTypes.func.isRequired,
onForgetDevice: PropTypes.func.isRequired, onForgetDevice: PropTypes.func.isRequired,
getPage: PropTypes.func.isRequired, getPage: PropTypes.func.isRequired,
network: PropTypes.string, chainId: PropTypes.string,
rpcPrefs: PropTypes.object,
selectedAccounts: PropTypes.array.isRequired, selectedAccounts: PropTypes.array.isRequired,
onUnlockAccounts: PropTypes.func, onUnlockAccounts: PropTypes.func,
onCancel: PropTypes.func, onCancel: PropTypes.func,

@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import * as actions from '../../../store/actions'; import * as actions from '../../../store/actions';
import { import {
getCurrentChainId,
getMetaMaskAccounts, getMetaMaskAccounts,
getRpcPrefsForCurrentProvider,
getMetaMaskAccountsConnected, getMetaMaskAccountsConnected,
} from '../../../selectors'; } from '../../../selectors';
import { formatBalance } from '../../../helpers/utils/util'; import { formatBalance } from '../../../helpers/utils/util';
@ -257,7 +259,8 @@ class ConnectHardwareForm extends Component {
connectedAccounts={this.props.connectedAccounts} connectedAccounts={this.props.connectedAccounts}
selectedAccounts={this.state.selectedAccounts} selectedAccounts={this.state.selectedAccounts}
onAccountChange={this.onAccountChange} onAccountChange={this.onAccountChange}
network={this.props.network} chainId={this.props.chainId}
rpcPrefs={this.props.rpcPrefs}
getPage={this.getPage} getPage={this.getPage}
onUnlockAccounts={this.onUnlockAccounts} onUnlockAccounts={this.onUnlockAccounts}
onForgetDevice={this.onForgetDevice} onForgetDevice={this.onForgetDevice}
@ -287,31 +290,22 @@ ConnectHardwareForm.propTypes = {
unlockHardwareWalletAccounts: PropTypes.func, unlockHardwareWalletAccounts: PropTypes.func,
setHardwareWalletDefaultHdPath: PropTypes.func, setHardwareWalletDefaultHdPath: PropTypes.func,
history: PropTypes.object, history: PropTypes.object,
network: PropTypes.string, chainId: PropTypes.string,
rpcPrefs: PropTypes.object,
accounts: PropTypes.object, accounts: PropTypes.object,
connectedAccounts: PropTypes.array.isRequired, connectedAccounts: PropTypes.array.isRequired,
defaultHdPaths: PropTypes.object, defaultHdPaths: PropTypes.object,
mostRecentOverviewPage: PropTypes.string.isRequired, mostRecentOverviewPage: PropTypes.string.isRequired,
}; };
const mapStateToProps = (state) => { const mapStateToProps = (state) => ({
const { chainId: getCurrentChainId(state),
metamask: { network }, rpcPrefs: getRpcPrefsForCurrentProvider(state),
} = state; accounts: getMetaMaskAccounts(state),
const accounts = getMetaMaskAccounts(state); connectedAccounts: getMetaMaskAccountsConnected(state),
const connectedAccounts = getMetaMaskAccountsConnected(state); defaultHdPaths: state.appState.defaultHdPaths,
const { mostRecentOverviewPage: getMostRecentOverviewPage(state),
appState: { defaultHdPaths }, });
} = state;
return {
network,
accounts,
connectedAccounts,
defaultHdPaths,
mostRecentOverviewPage: getMostRecentOverviewPage(state),
};
};
const mapDispatchToProps = (dispatch) => { const mapDispatchToProps = (dispatch) => {
return { return {

@ -1,4 +1,6 @@
export default function getAccountLink(address, network, rpcPrefs) { import { createAccountLinkForChain } from '@metamask/etherscan-link';
export default function getAccountLink(address, chainId, rpcPrefs) {
if (rpcPrefs && rpcPrefs.blockExplorerUrl) { if (rpcPrefs && rpcPrefs.blockExplorerUrl) {
return `${rpcPrefs.blockExplorerUrl.replace( return `${rpcPrefs.blockExplorerUrl.replace(
/\/+$/u, /\/+$/u,
@ -6,22 +8,5 @@ export default function getAccountLink(address, network, rpcPrefs) {
)}/address/${address}`; )}/address/${address}`;
} }
// eslint-disable-next-line radix return createAccountLinkForChain(address, chainId);
const net = parseInt(network);
switch (net) {
case 1: // main net
return `https://etherscan.io/address/${address}`;
case 2: // morden test net
return `https://morden.etherscan.io/address/${address}`;
case 3: // ropsten test net
return `https://ropsten.etherscan.io/address/${address}`;
case 4: // rinkeby test net
return `https://rinkeby.etherscan.io/address/${address}`;
case 42: // kovan test net
return `https://kovan.etherscan.io/address/${address}`;
case 5: // goerli test net
return `https://goerli.etherscan.io/address/${address}`;
default:
return '';
}
} }

Loading…
Cancel
Save