1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00

Disable Bridge button on unsupported networks (#18268)

This commit is contained in:
micaelae 2023-03-23 10:24:10 -07:00 committed by GitHub
parent 0351309227
commit 2fc0d93789
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 16 deletions

View File

@ -0,0 +1,10 @@
import { CHAIN_IDS } from './network';
export const ALLOWED_BRIDGE_CHAIN_IDS = [
CHAIN_IDS.MAINNET,
CHAIN_IDS.BSC,
CHAIN_IDS.POLYGON,
CHAIN_IDS.AVALANCHE,
CHAIN_IDS.OPTIMISM,
CHAIN_IDS.ARBITRUM,
];

View File

@ -19,6 +19,7 @@ import {
getCurrentKeyring, getCurrentKeyring,
getSwapsDefaultToken, getSwapsDefaultToken,
getIsSwapsChain, getIsSwapsChain,
getIsBridgeChain,
getIsBuyableChain, getIsBuyableChain,
getNativeCurrencyImage, getNativeCurrencyImage,
getSelectedAccountCachedBalance, getSelectedAccountCachedBalance,
@ -56,6 +57,7 @@ const EthOverview = ({ className }) => {
const showFiat = useSelector(getShouldShowFiat); const showFiat = useSelector(getShouldShowFiat);
const balance = useSelector(getSelectedAccountCachedBalance); const balance = useSelector(getSelectedAccountCachedBalance);
const isSwapsChain = useSelector(getIsSwapsChain); const isSwapsChain = useSelector(getIsSwapsChain);
const isBridgeChain = useSelector(getIsBridgeChain);
const isBuyableChain = useSelector(getIsBuyableChain); const isBuyableChain = useSelector(getIsBuyableChain);
const primaryTokenImage = useSelector(getNativeCurrencyImage); const primaryTokenImage = useSelector(getNativeCurrencyImage);
const defaultSwapsToken = useSelector(getSwapsDefaultToken); const defaultSwapsToken = useSelector(getSwapsDefaultToken);
@ -232,26 +234,41 @@ const EthOverview = ({ className }) => {
/> />
<IconButton <IconButton
className="eth-overview__button" className="eth-overview__button"
disabled={!isBridgeChain}
data-testid="eth-overview-bridge" data-testid="eth-overview-bridge"
Icon={ Icon={
<Icon name={ICON_NAMES.BRIDGE} color={IconColor.primaryInverse} /> <Icon name={ICON_NAMES.BRIDGE} color={IconColor.primaryInverse} />
} }
label={t('bridge')} label={t('bridge')}
onClick={() => { onClick={() => {
const portfolioUrl = process.env.PORTFOLIO_URL; if (isBridgeChain) {
const bridgeUrl = `${portfolioUrl}/bridge`; const portfolioUrl = process.env.PORTFOLIO_URL;
global.platform.openTab({ const bridgeUrl = `${portfolioUrl}/bridge`;
url: `${bridgeUrl}?metamaskEntry=ext`, global.platform.openTab({
}); url: `${bridgeUrl}?metamaskEntry=ext`,
trackEvent({ });
category: EVENT.CATEGORIES.NAVIGATION, trackEvent({
event: EVENT_NAMES.BRIDGE_LINK_CLICKED, category: EVENT.CATEGORIES.NAVIGATION,
properties: { event: EVENT_NAMES.BRIDGE_LINK_CLICKED,
location: 'Home', properties: {
text: 'Bridge', location: 'Home',
}, text: 'Bridge',
}); },
});
}
}} }}
tooltipRender={
isBridgeChain
? null
: (contents) => (
<Tooltip
title={t('currentlyUnavailable')}
position="bottom"
>
{contents}
</Tooltip>
)
}
/> />
</> </>
} }

View File

@ -145,13 +145,30 @@ describe('EthOverview', () => {
expect(secondaryBalance).toHaveTextContent('0'); expect(secondaryBalance).toHaveTextContent('0');
}); });
it('should always show the Bridge button', () => { it('should have the Bridge button enabled if chain id is part of supported chains', () => {
const { queryByTestId } = renderWithProvider(<EthOverview />, store); const mockedAvalancheStore = {
...mockStore,
metamask: {
...mockStore.metamask,
provider: { ...mockStore.metamask.provider, chainId: '0xa86a' },
},
};
const mockedStore = configureMockStore([thunk])(mockedAvalancheStore);
const { queryByTestId, queryByText } = renderWithProvider(
<EthOverview />,
mockedStore,
);
const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE); const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE);
expect(bridgeButton).toBeInTheDocument(); expect(bridgeButton).toBeInTheDocument();
expect(bridgeButton).toBeEnabled();
expect(queryByText('Bridge').parentElement).not.toHaveAttribute(
'data-original-title',
'Unavailable on this network',
);
}); });
it('should open the Bridge URI when clicking on Bridge button', async () => { it('should open the Bridge URI when clicking on Bridge button on supported network', async () => {
const { queryByTestId } = renderWithProvider(<EthOverview />, store); const { queryByTestId } = renderWithProvider(<EthOverview />, store);
const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE); const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE);
@ -169,6 +186,29 @@ describe('EthOverview', () => {
); );
}); });
it('should have the Bridge button disabled if chain id is not part of supported chains', () => {
const mockedFantomStore = {
...mockStore,
metamask: {
...mockStore.metamask,
provider: { ...mockStore.metamask.provider, chainId: '0xfa' },
},
};
const mockedStore = configureMockStore([thunk])(mockedFantomStore);
const { queryByTestId, queryByText } = renderWithProvider(
<EthOverview />,
mockedStore,
);
const bridgeButton = queryByTestId(ETH_OVERVIEW_BRIDGE);
expect(bridgeButton).toBeInTheDocument();
expect(bridgeButton).toBeDisabled();
expect(queryByText('Bridge').parentElement).toHaveAttribute(
'data-original-title',
'Unavailable on this network',
);
});
it('should always show the Portfolio button', () => { it('should always show the Portfolio button', () => {
const { queryByTestId } = renderWithProvider(<EthOverview />, store); const { queryByTestId } = renderWithProvider(<EthOverview />, store);
const portfolioButton = queryByTestId(ETH_OVERVIEW_PORTFOLIO); const portfolioButton = queryByTestId(ETH_OVERVIEW_PORTFOLIO);

View File

@ -22,6 +22,7 @@
border-radius: 18px; border-radius: 18px;
margin-top: 6px; margin-top: 6px;
margin-bottom: 5px; margin-bottom: 5px;
margin-inline: auto;
} }
&--disabled { &--disabled {

View File

@ -41,6 +41,8 @@ import {
ALLOWED_DEV_SWAPS_CHAIN_IDS, ALLOWED_DEV_SWAPS_CHAIN_IDS,
} from '../../shared/constants/swaps'; } from '../../shared/constants/swaps';
import { ALLOWED_BRIDGE_CHAIN_IDS } from '../../shared/constants/bridge';
import { import {
shortenAddress, shortenAddress,
getAccountByAddress, getAccountByAddress,
@ -750,6 +752,11 @@ export function getIsSwapsChain(state) {
: ALLOWED_DEV_SWAPS_CHAIN_IDS.includes(chainId); : ALLOWED_DEV_SWAPS_CHAIN_IDS.includes(chainId);
} }
export function getIsBridgeChain(state) {
const chainId = getCurrentChainId(state);
return ALLOWED_BRIDGE_CHAIN_IDS.includes(chainId);
}
export function getIsBuyableChain(state) { export function getIsBuyableChain(state) {
const chainId = getCurrentChainId(state); const chainId = getCurrentChainId(state);
return Object.keys(BUYABLE_CHAINS_MAP).includes(chainId); return Object.keys(BUYABLE_CHAINS_MAP).includes(chainId);

View File

@ -390,4 +390,14 @@ describe('Selectors', () => {
const isDesktopEnabled = selectors.getIsDesktopEnabled(mockState); const isDesktopEnabled = selectors.getIsDesktopEnabled(mockState);
expect(isDesktopEnabled).toBeFalsy(); expect(isDesktopEnabled).toBeFalsy();
}); });
it('#getIsBridgeChain', () => {
mockState.metamask.provider.chainId = '0xa';
const isOptimismSupported = selectors.getIsBridgeChain(mockState);
expect(isOptimismSupported).toBeTruthy();
mockState.metamask.provider.chainId = '0xfa';
const isFantomSupported = selectors.getIsBridgeChain(mockState);
expect(isFantomSupported).toBeFalsy();
});
}); });