mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
Show Bridge button in TokenOverview component (#18630)
* Show Bridge button in TokenOverview component * Hide Swap button in token overview page when network is not supported
This commit is contained in:
parent
8e6f4b8831
commit
a144b75fe8
@ -8,3 +8,46 @@ export const ALLOWED_BRIDGE_CHAIN_IDS = [
|
|||||||
CHAIN_IDS.OPTIMISM,
|
CHAIN_IDS.OPTIMISM,
|
||||||
CHAIN_IDS.ARBITRUM,
|
CHAIN_IDS.ARBITRUM,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const ALLOWED_BRIDGE_TOKEN_ADDRESSES = {
|
||||||
|
[CHAIN_IDS.MAINNET]: [
|
||||||
|
'0xdac17f958d2ee523a2206206994597c13d831ec7',
|
||||||
|
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
|
||||||
|
'0x6b175474e89094c44da98b954eedeac495271d0f',
|
||||||
|
'0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0',
|
||||||
|
'0x8965349fb649a33a30cbfda057d8ec2c48abe2a2',
|
||||||
|
],
|
||||||
|
[CHAIN_IDS.BSC]: [
|
||||||
|
'0x55d398326f99059ff775485246999027b3197955',
|
||||||
|
'0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d',
|
||||||
|
'0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3',
|
||||||
|
'0x2170ed0880ac9a755fd29b2688956bd959f933f8',
|
||||||
|
'0xcc42724c6683b7e57334c4e856f4c9965ed682bd',
|
||||||
|
'0x1ce0c2827e2ef14d5c4f29a091d735a204794041',
|
||||||
|
],
|
||||||
|
[CHAIN_IDS.POLYGON]: [
|
||||||
|
'0xc2132d05d31c914a87c6611c10748aeb04b58e8f',
|
||||||
|
'0x2791bca1f2de4661ed88a30c99a7a9449aa84174',
|
||||||
|
'0x8f3cf7ad23cd3cadbd9735aff958023239c6a063',
|
||||||
|
'0x7ceb23fd6bc0add59e62ac25578270cff1b9f619',
|
||||||
|
'0x2c89bbc92bd86f8075d1decc58c7f4e0107f286b',
|
||||||
|
],
|
||||||
|
[CHAIN_IDS.AVALANCHE]: [
|
||||||
|
'0xc7198437980c041c805a1edcba50c1ce5db95118',
|
||||||
|
'0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7',
|
||||||
|
'0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664',
|
||||||
|
'0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
|
||||||
|
'0xd586e7f844cea2f87f50152665bcbc2c279d8d70',
|
||||||
|
'0x49d5c2bdffac6ce2bfdb6640f4f80f226bc10bab',
|
||||||
|
],
|
||||||
|
[CHAIN_IDS.OPTIMISM]: [
|
||||||
|
'0x94b008aa00579c1307b0ef2c499ad98a8ce58e58',
|
||||||
|
'0x7f5c764cbc14f9669b88837ca1490cca17c31607',
|
||||||
|
'0xda10009cbd5d07dd0cecc66161fc93d7c9000da1',
|
||||||
|
],
|
||||||
|
[CHAIN_IDS.ARBITRUM]: [
|
||||||
|
'0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9',
|
||||||
|
'0xff970a61a04b1ca14834a43f5de4533ebddb5cc8',
|
||||||
|
'0xda10009cbd5d07dd0cecc66161fc93d7c9000da1',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
@ -2,7 +2,7 @@ import React, { useContext } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
|
|
||||||
import Identicon from '../../ui/identicon';
|
import Identicon from '../../ui/identicon';
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
@ -52,6 +52,7 @@ const EthOverview = ({ className }) => {
|
|||||||
const t = useContext(I18nContext);
|
const t = useContext(I18nContext);
|
||||||
const trackEvent = useContext(MetaMetricsContext);
|
const trackEvent = useContext(MetaMetricsContext);
|
||||||
const history = useHistory();
|
const history = useHistory();
|
||||||
|
const location = useLocation();
|
||||||
const keyring = useSelector(getCurrentKeyring);
|
const keyring = useSelector(getCurrentKeyring);
|
||||||
const usingHardwareWallet = isHardwareKeyring(keyring?.type);
|
const usingHardwareWallet = isHardwareKeyring(keyring?.type);
|
||||||
const balanceIsCached = useSelector(isBalanceCached);
|
const balanceIsCached = useSelector(isBalanceCached);
|
||||||
@ -246,7 +247,9 @@ const EthOverview = ({ className }) => {
|
|||||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||||
const bridgeUrl = `${portfolioUrl}/bridge`;
|
const bridgeUrl = `${portfolioUrl}/bridge`;
|
||||||
global.platform.openTab({
|
global.platform.openTab({
|
||||||
url: `${bridgeUrl}?metamaskEntry=ext`,
|
url: `${bridgeUrl}?metamaskEntry=ext_bridge_button${
|
||||||
|
location.pathname.includes('asset') ? '&token=native' : ''
|
||||||
|
}`,
|
||||||
});
|
});
|
||||||
trackEvent({
|
trackEvent({
|
||||||
category: MetaMetricsEventCategory.Navigation,
|
category: MetaMetricsEventCategory.Navigation,
|
||||||
|
@ -181,7 +181,9 @@ describe('EthOverview', () => {
|
|||||||
|
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(openTabSpy).toHaveBeenCalledWith({
|
expect(openTabSpy).toHaveBeenCalledWith({
|
||||||
url: expect.stringContaining(`/bridge?metamaskEntry=ext`),
|
url: expect.stringContaining(
|
||||||
|
'/bridge?metamaskEntry=ext_bridge_button',
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -114,7 +114,14 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 16px 0;
|
margin: 16px 0;
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
max-width: 100%;
|
max-width: 326px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__primary-container {
|
||||||
|
display: flex;
|
||||||
|
max-width: inherit;
|
||||||
|
justify-content: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__primary-balance {
|
&__primary-balance {
|
||||||
@ -131,6 +138,11 @@
|
|||||||
color: var(--color-text-alternative);
|
color: var(--color-text-alternative);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&__portfolio-button {
|
||||||
|
height: inherit;
|
||||||
|
padding-inline-start: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
&__button:last-of-type {
|
&__button:last-of-type {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
|
|
||||||
import Identicon from '../../ui/identicon';
|
import Identicon from '../../ui/identicon';
|
||||||
import Tooltip from '../../ui/tooltip';
|
|
||||||
import CurrencyDisplay from '../../ui/currency-display';
|
import CurrencyDisplay from '../../ui/currency-display';
|
||||||
import { I18nContext } from '../../../contexts/i18n';
|
import { I18nContext } from '../../../contexts/i18n';
|
||||||
import { isHardwareKeyring } from '../../../helpers/utils/hardware';
|
import { isHardwareKeyring } from '../../../helpers/utils/hardware';
|
||||||
@ -20,6 +19,7 @@ import {
|
|||||||
getCurrentKeyring,
|
getCurrentKeyring,
|
||||||
getIsSwapsChain,
|
getIsSwapsChain,
|
||||||
getIsBuyableChain,
|
getIsBuyableChain,
|
||||||
|
getIsBridgeToken,
|
||||||
} from '../../../selectors';
|
} from '../../../selectors';
|
||||||
|
|
||||||
import IconButton from '../../ui/icon-button';
|
import IconButton from '../../ui/icon-button';
|
||||||
@ -35,8 +35,10 @@ import {
|
|||||||
import { AssetType } from '../../../../shared/constants/transaction';
|
import { AssetType } from '../../../../shared/constants/transaction';
|
||||||
import useRamps from '../../../hooks/experiences/useRamps';
|
import useRamps from '../../../hooks/experiences/useRamps';
|
||||||
|
|
||||||
import { Icon, IconName } from '../../component-library';
|
import { ButtonIcon, Icon, IconName } from '../../component-library';
|
||||||
import { IconColor } from '../../../helpers/constants/design-system';
|
import { IconColor } from '../../../helpers/constants/design-system';
|
||||||
|
|
||||||
|
import { BUTTON_ICON_SIZES } from '../../component-library/button-icon/deprecated';
|
||||||
import WalletOverview from './wallet-overview';
|
import WalletOverview from './wallet-overview';
|
||||||
|
|
||||||
const TokenOverview = ({ className, token }) => {
|
const TokenOverview = ({ className, token }) => {
|
||||||
@ -55,7 +57,7 @@ const TokenOverview = ({ className, token }) => {
|
|||||||
token.symbol,
|
token.symbol,
|
||||||
);
|
);
|
||||||
const isSwapsChain = useSelector(getIsSwapsChain);
|
const isSwapsChain = useSelector(getIsSwapsChain);
|
||||||
|
const isBridgeToken = useSelector(getIsBridgeToken(token.address));
|
||||||
const isBuyableChain = useSelector(getIsBuyableChain);
|
const isBuyableChain = useSelector(getIsBuyableChain);
|
||||||
|
|
||||||
const { openBuyCryptoInPdapp } = useRamps();
|
const { openBuyCryptoInPdapp } = useRamps();
|
||||||
@ -75,11 +77,42 @@ const TokenOverview = ({ className, token }) => {
|
|||||||
<WalletOverview
|
<WalletOverview
|
||||||
balance={
|
balance={
|
||||||
<div className="token-overview__balance">
|
<div className="token-overview__balance">
|
||||||
<CurrencyDisplay
|
<div className="token-overview__primary-container">
|
||||||
className="token-overview__primary-balance"
|
<CurrencyDisplay
|
||||||
displayValue={balanceToRender}
|
style={{ display: 'contents' }}
|
||||||
suffix={token.symbol}
|
className="token-overview__primary-balance"
|
||||||
/>
|
displayValue={balanceToRender}
|
||||||
|
suffix={token.symbol}
|
||||||
|
/>
|
||||||
|
<ButtonIcon
|
||||||
|
className="token-overview__portfolio-button"
|
||||||
|
data-testid="home__portfolio-site"
|
||||||
|
color={IconColor.primaryDefault}
|
||||||
|
iconName={IconName.Diagram}
|
||||||
|
ariaLabel={t('portfolio')}
|
||||||
|
size={BUTTON_ICON_SIZES.LG}
|
||||||
|
onClick={() => {
|
||||||
|
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||||
|
global.platform.openTab({
|
||||||
|
url: `${portfolioUrl}?metamaskEntry=ext`,
|
||||||
|
});
|
||||||
|
trackEvent(
|
||||||
|
{
|
||||||
|
category: MetaMetricsEventCategory.Home,
|
||||||
|
event: MetaMetricsEventName.PortfolioLinkClicked,
|
||||||
|
properties: {
|
||||||
|
url: portfolioUrl,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
contextPropsIntoEventProperties: [
|
||||||
|
MetaMetricsContextProp.PageTitle,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
{formattedFiatBalance ? (
|
{formattedFiatBalance ? (
|
||||||
<CurrencyDisplay
|
<CurrencyDisplay
|
||||||
className="token-overview__secondary-balance"
|
className="token-overview__secondary-balance"
|
||||||
@ -145,17 +178,16 @@ const TokenOverview = ({ className, token }) => {
|
|||||||
data-testid="eth-overview-send"
|
data-testid="eth-overview-send"
|
||||||
disabled={token.isERC721}
|
disabled={token.isERC721}
|
||||||
/>
|
/>
|
||||||
<IconButton
|
{isSwapsChain && (
|
||||||
className="token-overview__button"
|
<IconButton
|
||||||
disabled={!isSwapsChain}
|
className="token-overview__button"
|
||||||
Icon={
|
Icon={
|
||||||
<Icon
|
<Icon
|
||||||
name={IconName.SwapHorizontal}
|
name={IconName.SwapHorizontal}
|
||||||
color={IconColor.primaryInverse}
|
color={IconColor.primaryInverse}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isSwapsChain) {
|
|
||||||
trackEvent({
|
trackEvent({
|
||||||
event: MetaMetricsEventName.NavSwapButtonClicked,
|
event: MetaMetricsEventName.NavSwapButtonClicked,
|
||||||
category: MetaMetricsEventCategory.Swaps,
|
category: MetaMetricsEventCategory.Swaps,
|
||||||
@ -179,51 +211,38 @@ const TokenOverview = ({ className, token }) => {
|
|||||||
} else {
|
} else {
|
||||||
history.push(BUILD_QUOTE_ROUTE);
|
history.push(BUILD_QUOTE_ROUTE);
|
||||||
}
|
}
|
||||||
|
}}
|
||||||
|
label={t('swap')}
|
||||||
|
tooltipRender={null}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isBridgeToken && (
|
||||||
|
<IconButton
|
||||||
|
className="token-overview__button"
|
||||||
|
data-testid="token-overview-bridge"
|
||||||
|
Icon={
|
||||||
|
<Icon name={IconName.Bridge} color={IconColor.primaryInverse} />
|
||||||
}
|
}
|
||||||
}}
|
label={t('bridge')}
|
||||||
label={t('swap')}
|
onClick={() => {
|
||||||
tooltipRender={
|
const portfolioUrl = process.env.PORTFOLIO_URL;
|
||||||
isSwapsChain
|
|
||||||
? null
|
const bridgeUrl = `${portfolioUrl}/bridge`;
|
||||||
: (contents) => (
|
global.platform.openTab({
|
||||||
<Tooltip
|
url: `${bridgeUrl}?metamaskEntry=ext_bridge_button&token=${token.address}`,
|
||||||
title={t('currentlyUnavailable')}
|
});
|
||||||
position="bottom"
|
trackEvent({
|
||||||
disabled={isSwapsChain}
|
category: MetaMetricsEventCategory.Navigation,
|
||||||
>
|
event: MetaMetricsEventName.BridgeLinkClicked,
|
||||||
{contents}
|
|
||||||
</Tooltip>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
<IconButton
|
|
||||||
className="eth-overview__button"
|
|
||||||
Icon={
|
|
||||||
<Icon name={IconName.Diagram} color={IconColor.primaryInverse} />
|
|
||||||
}
|
|
||||||
label={t('portfolio')}
|
|
||||||
data-testid="home__portfolio-site"
|
|
||||||
onClick={() => {
|
|
||||||
const portfolioUrl = process.env.PORTFOLIO_URL;
|
|
||||||
global.platform.openTab({
|
|
||||||
url: `${portfolioUrl}?metamaskEntry=ext`,
|
|
||||||
});
|
|
||||||
trackEvent(
|
|
||||||
{
|
|
||||||
category: MetaMetricsEventCategory.Home,
|
|
||||||
event: MetaMetricsEventName.PortfolioLinkClicked,
|
|
||||||
properties: {
|
properties: {
|
||||||
url: portfolioUrl,
|
location: 'Token Overview',
|
||||||
|
text: 'Bridge',
|
||||||
},
|
},
|
||||||
},
|
});
|
||||||
{
|
}}
|
||||||
contextPropsIntoEventProperties: [
|
tooltipRender={null}
|
||||||
MetaMetricsContextProp.PageTitle,
|
/>
|
||||||
],
|
)}
|
||||||
},
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
className={className}
|
className={className}
|
||||||
|
@ -23,6 +23,7 @@ jest.mock('../../../../shared/constants/network', () => ({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
let openTabSpy;
|
||||||
|
|
||||||
describe('TokenOverview', () => {
|
describe('TokenOverview', () => {
|
||||||
const mockStore = {
|
const mockStore = {
|
||||||
@ -68,6 +69,11 @@ describe('TokenOverview', () => {
|
|||||||
openTab: jest.fn(),
|
openTab: jest.fn(),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
openTabSpy = jest.spyOn(global.platform, 'openTab');
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
openTabSpy.mockClear();
|
||||||
});
|
});
|
||||||
|
|
||||||
const token = {
|
const token = {
|
||||||
@ -209,8 +215,6 @@ describe('TokenOverview', () => {
|
|||||||
mockedStoreWithBuyableChainId,
|
mockedStoreWithBuyableChainId,
|
||||||
);
|
);
|
||||||
|
|
||||||
const openTabSpy = jest.spyOn(global.platform, 'openTab');
|
|
||||||
|
|
||||||
const { queryByTestId } = renderWithProvider(
|
const { queryByTestId } = renderWithProvider(
|
||||||
<TokenOverview token={token} />,
|
<TokenOverview token={token} />,
|
||||||
mockedStore,
|
mockedStore,
|
||||||
@ -228,5 +232,137 @@ describe('TokenOverview', () => {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should always show the Portfolio button', () => {
|
||||||
|
const mockToken = {
|
||||||
|
name: 'test',
|
||||||
|
isERC721: false,
|
||||||
|
address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||||
|
symbol: 'test',
|
||||||
|
};
|
||||||
|
const { queryByTestId } = renderWithProvider(
|
||||||
|
<TokenOverview token={mockToken} />,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
const portfolioButton = queryByTestId('home__portfolio-site');
|
||||||
|
expect(portfolioButton).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should open the Portfolio URI when clicking on Portfolio button', async () => {
|
||||||
|
const mockToken = {
|
||||||
|
name: 'test',
|
||||||
|
isERC721: false,
|
||||||
|
address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||||
|
symbol: 'test',
|
||||||
|
};
|
||||||
|
const { queryByTestId } = renderWithProvider(
|
||||||
|
<TokenOverview token={mockToken} />,
|
||||||
|
store,
|
||||||
|
);
|
||||||
|
|
||||||
|
const portfolioButton = queryByTestId('home__portfolio-site');
|
||||||
|
|
||||||
|
expect(portfolioButton).toBeInTheDocument();
|
||||||
|
expect(portfolioButton).not.toBeDisabled();
|
||||||
|
|
||||||
|
fireEvent.click(portfolioButton);
|
||||||
|
expect(openTabSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(openTabSpy).toHaveBeenCalledWith({
|
||||||
|
url: expect.stringContaining(`?metamaskEntry=ext`),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show the Bridge button if chain id and token are supported', async () => {
|
||||||
|
const mockToken = {
|
||||||
|
name: 'test',
|
||||||
|
isERC721: false,
|
||||||
|
address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||||
|
symbol: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockedStoreWithBridgeableChainId = {
|
||||||
|
metamask: {
|
||||||
|
...mockStore.metamask,
|
||||||
|
provider: { type: 'test', chainId: CHAIN_IDS.POLYGON },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mockedStore = configureMockStore([thunk])(
|
||||||
|
mockedStoreWithBridgeableChainId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { queryByTestId } = renderWithProvider(
|
||||||
|
<TokenOverview token={mockToken} />,
|
||||||
|
mockedStore,
|
||||||
|
);
|
||||||
|
const bridgeButton = queryByTestId('token-overview-bridge');
|
||||||
|
expect(bridgeButton).toBeInTheDocument();
|
||||||
|
expect(bridgeButton).not.toBeDisabled();
|
||||||
|
|
||||||
|
fireEvent.click(bridgeButton);
|
||||||
|
expect(openTabSpy).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
await waitFor(() =>
|
||||||
|
expect(openTabSpy).toHaveBeenCalledWith({
|
||||||
|
url: expect.stringContaining(
|
||||||
|
'/bridge?metamaskEntry=ext_bridge_button&token=0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show the Bridge button if chain id is not supported', async () => {
|
||||||
|
const mockToken = {
|
||||||
|
name: 'test',
|
||||||
|
isERC721: false,
|
||||||
|
address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f619',
|
||||||
|
symbol: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockedStoreWithBridgeableChainId = {
|
||||||
|
metamask: {
|
||||||
|
...mockStore.metamask,
|
||||||
|
provider: { type: 'test', chainId: CHAIN_IDS.FANTOM },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mockedStore = configureMockStore([thunk])(
|
||||||
|
mockedStoreWithBridgeableChainId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { queryByTestId } = renderWithProvider(
|
||||||
|
<TokenOverview token={mockToken} />,
|
||||||
|
mockedStore,
|
||||||
|
);
|
||||||
|
const bridgeButton = queryByTestId('token-overview-bridge');
|
||||||
|
expect(bridgeButton).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not show the Bridge button if token is not supported', async () => {
|
||||||
|
const mockToken = {
|
||||||
|
name: 'test',
|
||||||
|
isERC721: false,
|
||||||
|
address: '0x7ceb23fd6bc0add59e62ac25578270cff1B9f620',
|
||||||
|
symbol: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockedStoreWithBridgeableChainId = {
|
||||||
|
metamask: {
|
||||||
|
...mockStore.metamask,
|
||||||
|
provider: { type: 'test', chainId: CHAIN_IDS.POLYGON },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mockedStore = configureMockStore([thunk])(
|
||||||
|
mockedStoreWithBridgeableChainId,
|
||||||
|
);
|
||||||
|
|
||||||
|
const { queryByTestId } = renderWithProvider(
|
||||||
|
<TokenOverview token={mockToken} />,
|
||||||
|
mockedStore,
|
||||||
|
);
|
||||||
|
const bridgeButton = queryByTestId('token-overview-bridge');
|
||||||
|
expect(bridgeButton).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -46,7 +46,10 @@ 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 {
|
||||||
|
ALLOWED_BRIDGE_CHAIN_IDS,
|
||||||
|
ALLOWED_BRIDGE_TOKEN_ADDRESSES,
|
||||||
|
} from '../../shared/constants/bridge';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
shortenAddress,
|
shortenAddress,
|
||||||
@ -747,6 +750,15 @@ export function getIsBridgeChain(state) {
|
|||||||
return ALLOWED_BRIDGE_CHAIN_IDS.includes(chainId);
|
return ALLOWED_BRIDGE_CHAIN_IDS.includes(chainId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getIsBridgeToken = (tokenAddress) => (state) => {
|
||||||
|
const chainId = getCurrentChainId(state);
|
||||||
|
const isBridgeChain = getIsBridgeChain(state);
|
||||||
|
return (
|
||||||
|
isBridgeChain &&
|
||||||
|
ALLOWED_BRIDGE_TOKEN_ADDRESSES[chainId].includes(tokenAddress.toLowerCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
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);
|
||||||
|
@ -450,4 +450,23 @@ describe('Selectors', () => {
|
|||||||
const isFantomSupported = selectors.getIsBridgeChain(mockState);
|
const isFantomSupported = selectors.getIsBridgeChain(mockState);
|
||||||
expect(isFantomSupported).toBeFalsy();
|
expect(isFantomSupported).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('#getIsBridgeToken', () => {
|
||||||
|
mockState.metamask.provider.chainId = '0xa';
|
||||||
|
const isOptimismTokenSupported = selectors.getIsBridgeToken(
|
||||||
|
'0x94B008aa00579c1307b0ef2c499ad98a8ce58e58',
|
||||||
|
)(mockState);
|
||||||
|
expect(isOptimismTokenSupported).toBeTruthy();
|
||||||
|
|
||||||
|
const isOptimismUnknownTokenSupported = selectors.getIsBridgeToken(
|
||||||
|
'0x94B008aa00579c1307b0ef2c499ad98a8ce58e60',
|
||||||
|
)(mockState);
|
||||||
|
expect(isOptimismUnknownTokenSupported).toBeFalsy();
|
||||||
|
|
||||||
|
mockState.metamask.provider.chainId = '0xfa';
|
||||||
|
const isFantomTokenSupported = selectors.getIsBridgeToken(
|
||||||
|
'0x94B008aa00579c1307b0ef2c499ad98a8ce58e58',
|
||||||
|
)(mockState);
|
||||||
|
expect(isFantomTokenSupported).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user