Skip to content

Commit

Permalink
feat(suite): legin and unverified token section in tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
tomasklim committed Feb 5, 2024
1 parent d418c85 commit 1d763fb
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 62 deletions.
171 changes: 109 additions & 62 deletions packages/suite/src/views/wallet/tokens/components/TokenList.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
import { useMemo, Fragment } from 'react';
import styled, { css, useTheme } from 'styled-components';
import { variables, Icon, Card } from '@trezor/components';
import { FiatValue, FormattedCryptoAmount, TrezorLink } from 'src/components/suite';
import {
FiatValue,
FormattedCryptoAmount,
QuestionTooltip,
TrezorLink,
} from 'src/components/suite';
import { Account } from 'src/types/wallet';
import { useSelector } from 'src/hooks/suite';
import { enhanceTokensWithRates, sortTokensWithRates } from '@suite-common/wallet-utils';
import { selectCoinsLegacy } from '@suite-common/wallet-core';
import { selectCoinsLegacy, selectTokenDefinitions } from '@suite-common/wallet-core';
import { NoRatesTooltip } from 'src/components/suite/Ticker/NoRatesTooltip';
import { FiatRates, TokenInfo } from '@trezor/blockchain-link-types';
import { spacingsPx } from '@trezor/theme';
import { getNetworkFeatures } from '@suite-common/wallet-config';

const Wrapper = styled(Card)<{ isTestnet?: boolean }>`
display: grid;
Expand Down Expand Up @@ -68,92 +76,131 @@ const StyledNoRatesTooltip = styled(NoRatesTooltip)`
justify-content: flex-end;
`;

const StyledQuestionTooltip = styled(QuestionTooltip)`
margin-top: ${spacingsPx.xxl};
margin-bottom: ${spacingsPx.sm};
`;

interface TokenListProps {
tokens: Account['tokens'];
networkType: Account['networkType'];
explorerUrl: string;
explorerUrlQueryString: string;
isTestnet?: boolean;
symbol: Account['symbol'];
}

type EnhancedTokenInfo = TokenInfo & { rates?: FiatRates };

export const TokenList = ({
tokens,
explorerUrl,
explorerUrlQueryString,
isTestnet,
networkType,
symbol,
}: TokenListProps) => {
const theme = useTheme();
const coins = useSelector(selectCoinsLegacy);
const tokenDefinitions = useSelector(state => selectTokenDefinitions(symbol)(state));

const sortedTokens = useMemo(() => {
const sortedTokens: EnhancedTokenInfo[] = useMemo(() => {
const tokensWithRates = enhanceTokensWithRates(tokens, coins);

return tokensWithRates.sort(sortTokensWithRates);
}, [tokens, coins]);

if (!tokens || tokens.length === 0) return null;

return (
<Wrapper isTestnet={isTestnet} paddingType="none">
{sortedTokens.map(t => {
// In Cardano token name is optional and in there is no symbol.
// However, if Cardano token doesn't have a name on blockchain, its TokenInfo has both name
// and symbol props set to a token fingerprint (done in blockchain-link) and we
// don't want to render it twice.
// In ethereum we are fine with rendering symbol - name even if they are the same.
const symbolMatchesName =
networkType === 'cardano' && t.symbol?.toLowerCase() === t.name?.toLowerCase();
const noSymbol = !t.symbol || symbolMatchesName;

const isTokenWithRate = Boolean(t.rates && Object.keys(t.rates).length);

return (
<Fragment key={t.contract}>
<Col isTestnet={isTestnet}>
{!noSymbol && <TokenSymbol>{t.symbol}</TokenSymbol>}
<TokenName>
{!noSymbol && ` - `}
{t.name}
</TokenName>
</Col>
<Col isTestnet={isTestnet} justify="right">
{t.balance && (
<CryptoAmount
value={t.balance}
symbol={networkType === 'cardano' ? undefined : t.symbol}
/>
)}
</Col>
{!isTestnet && (
<Col isTestnet={isTestnet} justify="right">
{t.balance && t.symbol && isTokenWithRate ? (
<FiatWrapper>
<FiatValue
amount={t.balance}
symbol={t.symbol}
tokenAddress={t.contract}
const hasNetworkFeatures = getNetworkFeatures(symbol).includes('token-definitions');
const { knownTokens, unknownTokens } = sortedTokens.reduce<{
knownTokens: EnhancedTokenInfo[];
unknownTokens: EnhancedTokenInfo[];
}>(
(acc, token) => {
if (tokenDefinitions[token.contract]?.isTokenKnown || !hasNetworkFeatures) {
acc.knownTokens.push(token);
} else {
acc.unknownTokens.push(token);
}
return acc;
},
{ knownTokens: [], unknownTokens: [] },
);

return [knownTokens, unknownTokens].map((tokens, index) =>
tokens.length ? (
<>
{index === 1 ? (
<StyledQuestionTooltip
label="TR_TOKEN_UNVERIFIED_BY_TREZOR"
tooltip="TR_TREZOR_UNVERIFIED_BY_TREZOR_TOOLTIP"
/>
) : null}
<Wrapper isTestnet={isTestnet} paddingType="none">
{tokens.map(t => {
// In Cardano token name is optional and in there is no symbol.
// However, if Cardano token doesn't have a name on blockchain, its TokenInfo has both name
// and symbol props set to a token fingerprint (done in blockchain-link) and we
// don't want to render it twice.
// In ethereum we are fine with rendering symbol - name even if they are the same.
const symbolMatchesName =
networkType === 'cardano' &&
t.symbol?.toLowerCase() === t.name?.toLowerCase();
const noSymbol = !t.symbol || symbolMatchesName;

const isTokenWithRate = Boolean(t.rates && Object.keys(t.rates).length);

return (
<Fragment key={t.contract}>
<Col isTestnet={isTestnet}>
{!noSymbol && <TokenSymbol>{t.symbol}</TokenSymbol>}
<TokenName>
{!noSymbol && ` - `}
{t.name}
</TokenName>
</Col>
<Col isTestnet={isTestnet} justify="right">
{t.balance && (
<CryptoAmount
value={t.balance}
symbol={
networkType === 'cardano' ? undefined : t.symbol
}
/>
</FiatWrapper>
) : (
<StyledNoRatesTooltip />
)}
</Col>
{!isTestnet && (
<Col isTestnet={isTestnet} justify="right">
{t.balance && t.symbol && isTokenWithRate ? (
<FiatWrapper>
<FiatValue
amount={t.balance}
symbol={t.symbol}
tokenAddress={t.contract}
/>
</FiatWrapper>
) : (
<StyledNoRatesTooltip />
)}
</Col>
)}
</Col>
)}
<Col isTestnet={isTestnet} justify="right">
<TrezorLink
href={`${explorerUrl}${t.contract}${explorerUrlQueryString}`}
>
<Icon
icon="EXTERNAL_LINK"
size={16}
color={theme.TYPE_LIGHT_GREY}
/>
</TrezorLink>
</Col>
</Fragment>
);
})}
</Wrapper>
<Col isTestnet={isTestnet} justify="right">
<TrezorLink
href={`${explorerUrl}${t.contract}${explorerUrlQueryString}`}
>
<Icon
icon="EXTERNAL_LINK"
size={16}
color={theme.TYPE_LIGHT_GREY}
/>
</TrezorLink>
</Col>
</Fragment>
);
})}
</Wrapper>
</>
) : null,
);
};
1 change: 1 addition & 0 deletions packages/suite/src/views/wallet/tokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const Tokens = () => {
explorerUrlQueryString={explorerUrlQueryString}
tokens={account.tokens}
networkType={account.networkType}
symbol={account.symbol}
/>
{!account.tokens?.length && <NoTokens />}
</WalletLayout>
Expand Down

0 comments on commit 1d763fb

Please sign in to comment.