Skip to content

Commit

Permalink
feat: add token verification source count and link to block explorer (#…
Browse files Browse the repository at this point in the history
…27759)

<!--
Please submit this PR as a draft initially.
Do not mark it as "Ready for review" until the template has been
completely filled out, and PR status checks have passed at least once.
-->

## **Description**

In a previous redesign, the information about the number of sources a
token has been verified on and the link to that token on the relevant
block explorer was removed from the swap page. This returns that
information.

<!--
Write a short description of the changes included in this pull request,
also include relevant motivation and context. Have in mind the following
questions:
1. What is the reason for the change?
2. What is the improvement/solution?
-->

[![Open in GitHub
Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/MetaMask/metamask-extension/pull/27759?quickstart=1)

## **Related issues**

Fixes:

## **Manual testing steps**

1. Go to the swap page
2. Select swap assets and amount
3. See token verification info and block explorer link

## **Screenshots/Recordings**

<!-- If applicable, add screenshots and/or recordings to visualize the
before and after of your change. -->

### **Before**
![Screenshot 2024-10-10 at 14 30
01](https://github.com/user-attachments/assets/85a3281e-a7b2-4649-9a72-7f756b233214)


<!-- [screenshots/recordings] -->

### **After**
![Screenshot 2024-10-10 at 14 30
21](https://github.com/user-attachments/assets/6f557ed5-a956-4ab8-b3bd-957ac4d9fc2a)

<!-- [screenshots/recordings] -->

## **Pre-merge author checklist**

- [x] I've followed [MetaMask Contributor
Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask
Extension Coding
Standards](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/CODING_GUIDELINES.md).
- [x] I've completed the PR template to the best of my ability
- [x] I’ve included tests if applicable
- [x] I’ve documented my code using [JSDoc](https://jsdoc.app/) format
if applicable
- [x] I’ve applied the right labels on the PR (see [labeling
guidelines](https://github.com/MetaMask/metamask-extension/blob/develop/.github/guidelines/LABELING_GUIDELINES.md)).
Not required for external contributors.

## **Pre-merge reviewer checklist**

- [ ] I've manually tested the PR (e.g. pull and build branch, run the
app, test code being changed).
- [ ] I confirm that this PR addresses all acceptance criteria described
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
  • Loading branch information
bfullam authored Nov 2, 2024
1 parent db2e8be commit d773dd6
Show file tree
Hide file tree
Showing 12 changed files with 136 additions and 74 deletions.
4 changes: 4 additions & 0 deletions app/_locales/en/messages.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

54 changes: 54 additions & 0 deletions shared/constants/common.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,59 @@
import { CHAIN_IDS } from './network';

export enum EtherDenomination {
ETH = 'ETH',
GWEI = 'GWEI',
WEI = 'WEI',
}

const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/';
const BSC_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'BscScan';
const MAINNET_DEFAULT_BLOCK_EXPLORER_URL = 'https://etherscan.io/';
const MAINNET_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'Etherscan';
const GOERLI_DEFAULT_BLOCK_EXPLORER_URL = 'https://goerli.etherscan.io/';
const GOERLI_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'Goerli Etherscan';
const POLYGON_DEFAULT_BLOCK_EXPLORER_URL = 'https://polygonscan.com/';
const POLYGON_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'PolygonScan';
const AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL = 'https://snowtrace.io/';
const AVALANCHE_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'Snowtrace';
const OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL = 'https://optimistic.etherscan.io/';
const OPTIMISM_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'Optimism Explorer';
const ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL = 'https://arbiscan.io/';
const ARBITRUM_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'ArbiScan';
const ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL = 'https://explorer.zksync.io/';
const ZKSYNC_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'Zksync Explorer';
const LINEA_DEFAULT_BLOCK_EXPLORER_URL = 'https://lineascan.build/';
const LINEA_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'LineaScan';
const BASE_DEFAULT_BLOCK_EXPLORER_URL = 'https://basescan.org/';
const BASE_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL = 'BaseScan';

type BlockExplorerUrlMap = {
[key: string]: string;
};

export const CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP: BlockExplorerUrlMap = {
[CHAIN_IDS.BSC]: BSC_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.MAINNET]: MAINNET_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.POLYGON]: POLYGON_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.GOERLI]: GOERLI_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.AVALANCHE]: AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.OPTIMISM]: OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.ARBITRUM]: ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.BASE]: BASE_DEFAULT_BLOCK_EXPLORER_URL,
} as const;

export const CHAINID_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL_MAP: BlockExplorerUrlMap =
{
[CHAIN_IDS.BSC]: BSC_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.MAINNET]: MAINNET_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.POLYGON]: POLYGON_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.GOERLI]: GOERLI_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.AVALANCHE]: AVALANCHE_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.OPTIMISM]: OPTIMISM_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.ARBITRUM]: ARBITRUM_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
[CHAIN_IDS.BASE]: BASE_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL,
} as const;
29 changes: 0 additions & 29 deletions shared/constants/swaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@ export type SwapsTokenObject = {
iconUrl: string;
};

type BlockExplorerUrlMap = {
[key: string]: string;
};

export const ETH_SWAPS_TOKEN_OBJECT: SwapsTokenObject = {
symbol: CURRENCY_SYMBOLS.ETH,
name: 'Ether',
Expand Down Expand Up @@ -174,17 +170,6 @@ export const TOKEN_API_BASE_URL = 'https://tokens.api.cx.metamask.io';
export const GAS_API_BASE_URL = 'https://gas.api.cx.metamask.io';
export const GAS_DEV_API_BASE_URL = 'https://gas.uat-api.cx.metamask.io';

const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/';
export const MAINNET_DEFAULT_BLOCK_EXPLORER_URL = 'https://etherscan.io/';
const GOERLI_DEFAULT_BLOCK_EXPLORER_URL = 'https://goerli.etherscan.io/';
const POLYGON_DEFAULT_BLOCK_EXPLORER_URL = 'https://polygonscan.com/';
const AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL = 'https://snowtrace.io/';
const OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL = 'https://optimistic.etherscan.io/';
const ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL = 'https://arbiscan.io/';
const ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL = 'https://explorer.zksync.io/';
export const LINEA_DEFAULT_BLOCK_EXPLORER_URL = 'https://lineascan.build/';
const BASE_DEFAULT_BLOCK_EXPLORER_URL = 'https://basescan.org/';

export const ALLOWED_PROD_SWAPS_CHAIN_IDS = [
CHAIN_IDS.MAINNET,
SWAPS_TESTNET_CHAIN_ID,
Expand Down Expand Up @@ -298,20 +283,6 @@ export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = {
[CHAIN_IDS.BASE]: BASE_SWAPS_TOKEN_OBJECT,
} as const;

export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP: BlockExplorerUrlMap =
{
[CHAIN_IDS.BSC]: BSC_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.MAINNET]: MAINNET_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.POLYGON]: POLYGON_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.GOERLI]: GOERLI_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.AVALANCHE]: AVALANCHE_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.OPTIMISM]: OPTIMISM_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.ARBITRUM]: ARBITRUM_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.ZKSYNC_ERA]: ZKSYNC_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.LINEA_MAINNET]: LINEA_DEFAULT_BLOCK_EXPLORER_URL,
[CHAIN_IDS.BASE]: BASE_DEFAULT_BLOCK_EXPLORER_URL,
} as const;

export const ETHEREUM = 'ethereum';
export const POLYGON = 'polygon';
export const BSC = 'bsc';
Expand Down
4 changes: 2 additions & 2 deletions ui/components/app/assets/nfts/nft-details/nft-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import { MetaMetricsContext } from '../../../../../contexts/metametrics';
import { Content, Footer, Page } from '../../../../multichain/pages/page';
import { formatCurrency } from '../../../../../helpers/utils/confirm-tx.util';
import { getShortDateFormatterV2 } from '../../../../../pages/asset/util';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../../shared/constants/swaps';
import { CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../../shared/constants/common';
import { getConversionRate } from '../../../../../ducks/metamask/metamask';
import { Numeric } from '../../../../../../shared/modules/Numeric';
// TODO: Remove restricted import
Expand Down Expand Up @@ -277,7 +277,7 @@ export default function NftDetails({ nft }: { nft: Nft }) {
null as unknown as string, // no holderAddress
{
blockExplorerUrl:
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
},
);
};
Expand Down
4 changes: 2 additions & 2 deletions ui/pages/institutional/account-list/account-list.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import CustodyLabels from '../../../components/institutional/custody-labels';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps';
import { CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/common';
import { CHAIN_IDS } from '../../../../shared/constants/network';
import { shortenAddress } from '../../../helpers/utils/util';
import Tooltip from '../../../components/ui/tooltip';
Expand Down Expand Up @@ -41,7 +41,7 @@ type CustodyAccountListProps = {
};

const getButtonLinkHref = (account: Account) => {
const url = SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET];
const url = CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET];
return `${url}address/${account.address}`;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useHistory } from 'react-router-dom';
import thunk from 'redux-thunk';
import { renderWithProvider } from '../../../../test/lib/render-helpers';
import mockState from '../../../../test/data/mock-state.json';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps';
import { CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/common';
import { CHAIN_IDS } from '../../../../shared/constants/network';
import { shortenAddress } from '../../../helpers/utils/util';
import { getSelectedInternalAccountFromMockState } from '../../../../test/jest/mocks';
Expand Down Expand Up @@ -145,7 +145,7 @@ describe('Interactive Replacement Token Page', function () {

it('should render all the accounts correctly', async () => {
const expectedHref = `${
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET]
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET]
}address/${custodianAddress}`;

await act(async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import { getMetaMaskAccounts } from '../../../selectors';
import { getInstitutionalConnectRequests } from '../../../ducks/institutional/institutional';
import { getSelectedInternalAccount } from '../../../selectors/accounts';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps';
import { CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/common';
import { CHAIN_IDS } from '../../../../shared/constants/network';
import {
mmiActionsFactory,
Expand All @@ -43,7 +43,7 @@ import { getMostRecentOverviewPage } from '../../../ducks/history/history';
import { shortenAddress } from '../../../helpers/utils/util';

const getButtonLinkHref = ({ address }: { address: string }) => {
const url = SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET];
const url = CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[CHAIN_IDS.MAINNET];
return `${url}address/${address}`;
};

Expand Down
4 changes: 2 additions & 2 deletions ui/pages/swaps/awaiting-swap/awaiting-swap.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ import {
QUOTES_NOT_AVAILABLE_ERROR,
CONTRACT_DATA_DISABLED_ERROR,
OFFLINE_FOR_MAINTENANCE,
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP,
} from '../../../../shared/constants/swaps';
import { CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/common';
import { isSwapsDefaultTokenSymbol } from '../../../../shared/modules/swaps.utils';
import PulseLoader from '../../../components/ui/pulse-loader';

Expand Down Expand Up @@ -143,7 +143,7 @@ export default function AwaitingSwap({
};
const baseNetworkUrl =
rpcPrefs.blockExplorerUrl ??
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ??
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ??
null;
const blockExplorerUrl = getBlockExplorerLink(
{ hash: txHash, chainId },
Expand Down
83 changes: 58 additions & 25 deletions ui/pages/swaps/prepare-swap-page/prepare-swap-page.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import React, { useContext, useEffect, useState, useCallback } from 'react';
import BigNumber from 'bignumber.js';
import PropTypes from 'prop-types';
import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { uniqBy, isEqual } from 'lodash';
import { uniqBy, isEqual, isEmpty } from 'lodash';
import { useHistory } from 'react-router-dom';
import { getTokenTrackerLink } from '@metamask/etherscan-link';
import { getAccountLink, getTokenTrackerLink } from '@metamask/etherscan-link';
import classnames from 'classnames';

import { MetaMetricsContext } from '../../../contexts/metametrics';
Expand Down Expand Up @@ -83,23 +83,23 @@ import { usePrevious } from '../../../hooks/usePrevious';
import { useTokenTracker } from '../../../hooks/useTokenTracker';
import { useTokenFiatAmount } from '../../../hooks/useTokenFiatAmount';
import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount';
import {
isSwapsDefaultTokenAddress,
isSwapsDefaultTokenSymbol,
} from '../../../../shared/modules/swaps.utils';
import { isSwapsDefaultTokenAddress } from '../../../../shared/modules/swaps.utils';
import {
MetaMetricsEventCategory,
MetaMetricsEventLinkType,
MetaMetricsEventName,
} from '../../../../shared/constants/metametrics';
import {
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP,
TokenBucketPriority,
ERROR_FETCHING_QUOTES,
QUOTES_NOT_AVAILABLE_ERROR,
QUOTES_EXPIRED_ERROR,
MAX_ALLOWED_SLIPPAGE,
} from '../../../../shared/constants/swaps';
import {
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP,
CHAINID_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL_MAP,
} from '../../../../shared/constants/common';
import {
resetSwapsPostFetchState,
ignoreTokens,
Expand Down Expand Up @@ -142,6 +142,7 @@ import SwapsBannerAlert from '../swaps-banner-alert/swaps-banner-alert';
import SwapsFooter from '../swaps-footer';
import SelectedToken from '../selected-token/selected-token';
import ListWithSearch from '../list-with-search/list-with-search';
import { CHAIN_IDS } from '../../../../shared/constants/network';
import QuotesLoadingAnimation from './quotes-loading-animation';
import ReviewQuote from './review-quote';

Expand Down Expand Up @@ -228,8 +229,8 @@ export default function PrepareSwapPage({
const isMetaMetricsEnabled = useSelector(getParticipateInMetaMetrics);
const isMarketingEnabled = useSelector(getDataCollectionForMarketing);

const fetchParamsFromToken = isSwapsDefaultTokenSymbol(
sourceTokenInfo?.symbol,
const fetchParamsFromToken = isSwapsDefaultTokenAddress(
sourceTokenInfo?.address,
chainId,
)
? defaultSwapsToken
Expand All @@ -241,7 +242,8 @@ export default function PrepareSwapPage({
// but is not in tokensWithBalances or tokens, then we want to add it to the usersTokens array so that
// the balance of the token can appear in the from token selection dropdown
const fromTokenArray =
!isSwapsDefaultTokenSymbol(fromToken?.symbol, chainId) && fromToken?.balance
!isSwapsDefaultTokenAddress(fromToken?.address, chainId) &&
fromToken?.balance
? [fromToken]
: [];
const usersTokens = uniqBy(
Expand Down Expand Up @@ -310,7 +312,10 @@ export default function PrepareSwapPage({
{ showFiat: true },
true,
);
const swapFromFiatValue = isSwapsDefaultTokenSymbol(fromTokenSymbol, chainId)
const swapFromFiatValue = isSwapsDefaultTokenAddress(
fromTokenAddress,
chainId,
)
? swapFromEthFiatValue
: swapFromTokenFiatValue;

Expand Down Expand Up @@ -435,19 +440,27 @@ export default function PrepareSwapPage({
onInputChange(fromTokenInputValue, token.string, token.decimals);
};

const blockExplorerTokenLink = getTokenTrackerLink(
selectedToToken.address,
chainId,
null, // no networkId
null, // no holderAddress
{
blockExplorerUrl:
SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
},
);
const blockExplorerTokenLink =
chainId === CHAIN_IDS.ZKSYNC_ERA
? // Use getAccountLink because zksync explorer uses a /address URL scheme instead of /token
getAccountLink(selectedToToken.address, chainId, {
blockExplorerUrl:
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
})
: getTokenTrackerLink(
selectedToToken.address,
chainId,
null, // no networkId
null, // no holderAddress
{
blockExplorerUrl:
CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? null,
},
);

const blockExplorerLabel = rpcPrefs.blockExplorerUrl
? getURLHostName(blockExplorerTokenLink)
? CHAINID_DEFAULT_BLOCK_EXPLORER_HUMAN_READABLE_URL_MAP[chainId] ??
t('etherscan')
: t('etherscan');

const { address: toAddress } = toToken || {};
Expand Down Expand Up @@ -786,18 +799,23 @@ export default function PrepareSwapPage({
);
}

const isNonDefaultToken = !isSwapsDefaultTokenSymbol(
fromTokenSymbol,
const isNonDefaultFromToken = !isSwapsDefaultTokenAddress(
fromTokenAddress,
chainId,
);
const hasPositiveFromTokenBalance = rawFromTokenBalance > 0;
const isTokenEligibleForMaxBalance =
isSmartTransaction || (!isSmartTransaction && isNonDefaultToken);
isSmartTransaction || (!isSmartTransaction && isNonDefaultFromToken);
const showMaxBalanceLink =
fromTokenSymbol &&
isTokenEligibleForMaxBalance &&
hasPositiveFromTokenBalance;

const isNonDefaultToToken = !isSwapsDefaultTokenAddress(
selectedToToken.address,
chainId,
);

return (
<div className="prepare-swap-page">
<div className="prepare-swap-page__content">
Expand Down Expand Up @@ -1024,6 +1042,21 @@ export default function PrepareSwapPage({
{selectedToToken?.string && yourTokenToBalance}
</div>
</Box>
<Box
display={DISPLAY.FLEX}
justifyContent={JustifyContent.spaceBetween}
alignItems={AlignItems.stretch}
>
<div className="prepare-swap-page__balance-message">
{selectedToToken &&
!isEmpty(selectedToToken) &&
isNonDefaultToToken &&
t('swapTokenVerifiedSources', [
occurrences,
<BlockExplorerLink key="block-explorer-link" />,
])}
</div>
</Box>
</div>
{showCrossChainSwapsLink && (
<ButtonLink
Expand Down
Loading

0 comments on commit d773dd6

Please sign in to comment.