Commit 21e1fdee authored by Igor Stuev's avatar Igor Stuev Committed by GitHub

token in token transfer is possibly null (#2396)

* token in token transfer is possibly null

* show transfer type if no token
parent db405c1c
import type { TokenInfo } from 'types/api/token';
import type { TokenTransfer, TokenTransferResponse } from 'types/api/tokenTransfer';
export const erc20: TokenTransfer = {
......@@ -146,7 +147,7 @@ export const erc1155A: TokenTransfer = {
export const erc1155B: TokenTransfer = {
...erc1155A,
token: {
...erc1155A.token,
...(erc1155A.token as TokenInfo<'ERC-1155'>),
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
......@@ -156,7 +157,7 @@ export const erc1155B: TokenTransfer = {
export const erc1155C: TokenTransfer = {
...erc1155A,
token: {
...erc1155A.token,
...(erc1155A.token as TokenInfo<'ERC-1155'>),
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
......@@ -166,7 +167,7 @@ export const erc1155C: TokenTransfer = {
export const erc1155D: TokenTransfer = {
...erc1155A,
token: {
...erc1155A.token,
...(erc1155A.token as TokenInfo<'ERC-1155'>),
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
......@@ -225,7 +226,7 @@ export const erc404A: TokenTransfer = {
export const erc404B: TokenTransfer = {
...erc404A,
token: {
...erc404A.token,
...(erc404A.token as TokenInfo<'ERC-404'>),
name: 'SastanaNFT',
symbol: 'ipfs://QmUpFUfVKDCWeZQk5pvDFUxnpQP9N6eLSHhNUy49T1JVtY',
},
......
......@@ -26,19 +26,19 @@ export type Erc404TotalPayload = {
export type TokenTransfer = (
{
token: TokenInfo<'ERC-20'>;
token: TokenInfo<'ERC-20'> | null;
total: Erc20TotalPayload | null;
} |
{
token: TokenInfo<'ERC-721'>;
token: TokenInfo<'ERC-721'> | null;
total: Erc721TotalPayload | null;
} |
{
token: TokenInfo<'ERC-1155'>;
token: TokenInfo<'ERC-1155'> | null;
total: Erc1155TotalPayload | null;
} |
{
token: TokenInfo<'ERC-404'>;
token: TokenInfo<'ERC-404'> | null;
total: Erc404TotalPayload | null;
}
) & TokenTransferBase;
......
......@@ -54,7 +54,7 @@ const matchFilters = (filters: Filters, tokenTransfer: TokenTransfer, address?:
}
}
if (filters.type && filters.type.length) {
if (!filters.type.includes(tokenTransfer.token.type)) {
if (!tokenTransfer.token || !filters.type.includes(tokenTransfer.token.type)) {
return false;
}
}
......
......@@ -170,7 +170,7 @@ const TokenPageContent = () => {
{
id: 'token_transfers',
title: 'Token transfers',
component: <TokenTransfer transfersQuery={ transfersQuery } token={ tokenQuery.data } shouldRender={ !isLoading }/>,
component: <TokenTransfer transfersQuery={ transfersQuery } tokenQuery={ tokenQuery } shouldRender={ !isLoading }/>,
},
{
id: 'holders',
......
......@@ -97,7 +97,7 @@ const TokenInstanceContent = () => {
{
id: 'token_transfers',
title: 'Token transfers',
component: <TokenTransfer transfersQuery={ transfersQuery } tokenId={ id } token={ tokenQuery.data } shouldRender={ !isLoading }/>,
component: <TokenTransfer transfersQuery={ transfersQuery } tokenId={ id } tokenQuery={ tokenQuery } shouldRender={ !isLoading }/>,
},
shouldFetchHolders ?
{ id: 'holders', title: 'Holders', component: <TokenHolders holdersQuery={ holdersQuery } token={ tokenQuery.data } shouldRender={ !isLoading }/> } :
......
......@@ -38,7 +38,7 @@ const TokenTransferListItem = ({
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
exchangeRate: token.exchange_rate,
exchangeRate: token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: total.decimals || '0',
......@@ -48,21 +48,27 @@ const TokenTransferListItem = ({
<ListItemMobile rowGap={ 3 } isAnimated>
<Flex w="100%" justifyContent="space-between">
<Flex flexWrap="wrap" rowGap={ 1 } mr={ showTxInfo && txHash ? 2 : 0 } columnGap={ 2 } overflow="hidden">
<TokenEntity
token={ token }
isLoading={ isLoading }
noSymbol
noCopy
w="auto"
/>
<Tag flexShrink={ 0 } isLoading={ isLoading }>{ getTokenTypeName(token.type) }</Tag>
{ token && (
<>
<TokenEntity
token={ token }
isLoading={ isLoading }
noSymbol
noCopy
w="auto"
/>
<Tag flexShrink={ 0 } isLoading={ isLoading }>{ getTokenTypeName(token.type) }</Tag>
</>
) }
<Tag colorScheme="orange" isLoading={ isLoading }>{ getTokenTransferTypeText(type) }</Tag>
</Flex>
{ showTxInfo && txHash && (
<TxAdditionalInfo hash={ txHash } isMobile isLoading={ isLoading }/>
) }
</Flex>
{ total && 'token_id' in total && total.token_id !== null && <NftEntity hash={ token.address } id={ total.token_id } isLoading={ isLoading }/> }
{ total && 'token_id' in total && total.token_id !== null && token && (
<NftEntity hash={ token.address } id={ total.token_id } isLoading={ isLoading }/>
) }
{ showTxInfo && txHash && (
<Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%">
<TxEntity
......
......@@ -37,7 +37,7 @@ const TokenTransferTableItem = ({
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
exchangeRate: token.exchange_rate,
exchangeRate: token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: total.decimals || '0',
......@@ -53,20 +53,30 @@ const TokenTransferTableItem = ({
</Td>
) }
<Td>
<TokenEntity
token={ token }
isLoading={ isLoading }
noSymbol
noCopy
mt={ 1 }
/>
<Flex columnGap={ 2 } rowGap={ 2 } mt={ 2 } flexWrap="wrap">
<Tag isLoading={ isLoading }>{ getTokenTypeName(token.type) }</Tag>
<Tag colorScheme="orange" isLoading={ isLoading }>{ getTokenTransferTypeText(type) }</Tag>
</Flex>
{ token ? (
<>
<TokenEntity
token={ token }
isLoading={ isLoading }
noSymbol
noCopy
mt={ 1 }
/>
<Flex columnGap={ 2 } rowGap={ 2 } mt={ 2 } flexWrap="wrap">
<Tag isLoading={ isLoading }>{ getTokenTypeName(token.type) }</Tag>
<Tag colorScheme="orange" isLoading={ isLoading }>{ getTokenTransferTypeText(type) }</Tag>
</Flex>
</>
) : 'N/A' }
</Td>
<Td>
{ total && 'token_id' in total && total.token_id !== null && <NftEntity hash={ token.address } id={ total.token_id } isLoading={ isLoading }/> }
{ total && 'token_id' in total && total.token_id !== null && token && (
<NftEntity
hash={ token.address }
id={ total.token_id }
isLoading={ isLoading }
/>
) }
</Td>
{ showTxInfo && txHash && (
<Td>
......
......@@ -28,7 +28,7 @@ const TokenTransferSnippet = ({ data, isLoading, noAddressIcons = true }: Props)
return <Skeleton w="250px" h={ 6 }/>;
}
switch (data.token.type) {
switch (data.token?.type) {
case 'ERC-20': {
const total = data.total as Erc20TotalPayload | null;
if (total === null || total.value === null) {
......@@ -82,6 +82,9 @@ const TokenTransferSnippet = ({ data, isLoading, noAddressIcons = true }: Props)
return <TokenTransferSnippetFiat token={ data.token } value={ total.value } decimals={ total.decimals }/>;
}
}
default: {
return null;
}
}
})();
......
import { Box } from '@chakra-ui/react';
import React from 'react';
import { tokenInfoERC20a, tokenInfoERC721a, tokenInfoERC1155a } from 'mocks/tokens/tokenInfo';
import * as tokenTransferMock from 'mocks/tokens/tokenTransfer';
import { test, expect } from 'playwright/lib';
......@@ -21,6 +22,10 @@ test('erc20 +@mobile', async({ render }) => {
// @ts-ignore:
pagination: { page: 1, isVisible: true },
}}
// @ts-ignore:
tokenQuery={{
data: tokenInfoERC20a,
}}
/>
</Box>,
);
......@@ -43,6 +48,10 @@ test('erc721 +@mobile', async({ render }) => {
// @ts-ignore:
pagination: { page: 1, isVisible: true },
}}
// @ts-ignore:
tokenQuery={{
data: tokenInfoERC721a,
}}
/>
</Box>,
);
......@@ -70,6 +79,10 @@ test('erc1155 +@mobile', async({ render }) => {
// @ts-ignore:
pagination: { page: 1, isVisible: true },
}}
// @ts-ignore:
tokenQuery={{
data: tokenInfoERC1155a,
}}
/>
</Box>,
);
......
import { Box } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { TokenInfo } from 'types/api/token';
import type { ResourceError } from 'lib/api/resources';
import useGradualIncrement from 'lib/hooks/useGradualIncrement';
import useIsMobile from 'lib/hooks/useIsMobile';
import useIsMounted from 'lib/hooks/useIsMounted';
......@@ -23,15 +25,16 @@ const TABS_HEIGHT = 88;
type Props = {
transfersQuery: QueryWithPagesResult<'token_transfers'> | QueryWithPagesResult<'token_instance_transfers'>;
tokenId?: string;
token?: TokenInfo;
tokenQuery: UseQueryResult<TokenInfo, ResourceError<unknown>>;
shouldRender?: boolean;
};
const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }: Props) => {
const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = true }: Props) => {
const isMobile = useIsMobile();
const isMounted = useIsMounted();
const router = useRouter();
const { isError, isPlaceholderData, data, pagination } = transfersQuery;
const { data: token, isPlaceholderData: isTokenPlaceholderData, isError: isTokenError } = tokenQuery;
const [ newItemsCount, setNewItemsCount ] = useGradualIncrement(0);
const [ socketAlert, setSocketAlert ] = React.useState('');
......@@ -64,7 +67,9 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }:
return null;
}
const content = data?.items ? (
const isLoading = isPlaceholderData || isTokenPlaceholderData;
const content = data?.items && token ? (
<>
<Box display={{ base: 'none', lg: 'block' }}>
<TokenTransferTable
......@@ -75,7 +80,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }:
socketInfoNum={ newItemsCount }
tokenId={ tokenId }
token={ token }
isLoading={ isPlaceholderData }
isLoading={ isLoading }
/>
</Box>
<Box display={{ base: 'block', lg: 'none' }}>
......@@ -85,10 +90,10 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }:
num={ newItemsCount }
alert={ socketAlert }
type="token_transfer"
isLoading={ isPlaceholderData }
isLoading={ isLoading }
/>
) }
<TokenTransferList data={ data?.items } tokenId={ tokenId } isLoading={ isPlaceholderData }/>
<TokenTransferList data={ data?.items } tokenId={ tokenId } isLoading={ isLoading }/>
</Box>
</>
) : null;
......@@ -101,7 +106,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }:
return (
<DataListDisplay
isError={ isError }
isError={ isError || isTokenError }
items={ data?.items }
emptyText="There are no token transfers."
content={ content }
......
......@@ -28,7 +28,7 @@ const TokenTransferListItem = ({
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
exchangeRate: token.exchange_rate,
exchangeRate: token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: total.decimals || '0',
......@@ -58,11 +58,11 @@ const TokenTransferListItem = ({
from={ from }
to={ to }
isLoading={ isLoading }
tokenHash={ token.address }
tokenHash={ token?.address }
w="100%"
fontWeight="500"
/>
{ valueStr && (token.type === 'ERC-20' || token.type === 'ERC-1155') && (
{ valueStr && token && (token.type === 'ERC-20' || token.type === 'ERC-1155') && (
<Grid gap={ 2 } templateColumns={ `1fr auto auto${ usd ? ' auto' : '' }` }>
<Skeleton isLoaded={ !isLoading } flexShrink={ 0 } fontWeight={ 500 }>
Value
......@@ -89,7 +89,7 @@ const TokenTransferListItem = ({
) }
</Grid>
) }
{ total && 'token_id' in total && (NFT_TOKEN_TYPE_IDS.includes(token.type)) && total.token_id !== null && (
{ total && 'token_id' in total && token && (NFT_TOKEN_TYPE_IDS.includes(token.type)) && total.token_id !== null && (
<NftEntity
hash={ token.address }
id={ total.token_id }
......
......@@ -19,11 +19,12 @@ interface Props {
socketInfoNum?: number;
tokenId?: string;
isLoading?: boolean;
token?: TokenInfo;
token: TokenInfo;
}
const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socketInfoNum, tokenId, isLoading, token }: Props) => {
const tokenType = data[0].token.type;
const tokenType = token.type;
return (
<AddressHighlightProvider>
......
......@@ -26,7 +26,7 @@ const TokenTransferTableItem = ({
}: Props) => {
const { usd, valueStr } = total && 'value' in total && total.value !== null ? getCurrencyValue({
value: total.value,
exchangeRate: token.exchange_rate,
exchangeRate: token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: total.decimals || '0',
......@@ -68,12 +68,12 @@ const TokenTransferTableItem = ({
isLoading={ isLoading }
mt="5px"
mode={{ lg: 'compact', xl: 'long' }}
tokenHash={ token.address }
tokenHash={ token?.address }
/>
</Td>
{ (NFT_TOKEN_TYPE_IDS.includes(token.type)) && (
{ (token && NFT_TOKEN_TYPE_IDS.includes(token.type)) && (
<Td>
{ total && 'token_id' in total && total.token_id !== null ? (
{ total && 'token_id' in total && token && total.token_id !== null ? (
<NftEntity
hash={ token.address }
id={ total.token_id }
......@@ -84,7 +84,7 @@ const TokenTransferTableItem = ({
}
</Td>
) }
{ (token.type === 'ERC-20' || token.type === 'ERC-1155' || token.type === 'ERC-404') && (
{ token && (token.type === 'ERC-20' || token.type === 'ERC-1155' || token.type === 'ERC-404') && (
<Td isNumeric verticalAlign="top">
{ valueStr && (
<Skeleton isLoaded={ !isLoading } display="inline-block" mt="7px" wordBreak="break-all">
......
......@@ -23,7 +23,7 @@ const TokenTransfersListItem = ({ item, isLoading }: Props) => {
const { valueStr } = item.total && 'value' in item.total && item.total.value !== null ? getCurrencyValue({
value: item.total.value,
exchangeRate: item.token.exchange_rate,
exchangeRate: item.token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: item.total.decimals || '0',
......@@ -68,7 +68,7 @@ const TokenTransfersListItem = ({ item, isLoading }: Props) => {
<AddressEntity address={ item.to } isLoading={ isLoading } truncation="constant"/>
</ListItemMobileGrid.Value>
{ item.total && 'token_id' in item.total && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null && (
{ item.total && 'token_id' in item.total && item.token && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null && (
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>Token ID</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value overflow="hidden">
......@@ -82,7 +82,7 @@ const TokenTransfersListItem = ({ item, isLoading }: Props) => {
</>
) }
{ valueStr && (item.token.type === 'ERC-20' || item.token.type === 'ERC-1155') && (
{ valueStr && item.token && (item.token.type === 'ERC-20' || item.token.type === 'ERC-1155') && (
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>Amount</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value>
......
......@@ -21,7 +21,7 @@ type Props = {
const TokenTransferTableItem = ({ item, isLoading }: Props) => {
const { valueStr } = item.total && 'value' in item.total && item.total.value !== null ? getCurrencyValue({
value: item.total.value,
exchangeRate: item.token.exchange_rate,
exchangeRate: item.token?.exchange_rate,
accuracy: 8,
accuracyUsd: 2,
decimals: item.total.decimals || '0',
......@@ -62,7 +62,7 @@ const TokenTransferTableItem = ({ item, isLoading }: Props) => {
/>
</Td>
<Td>
{ item.total && 'token_id' in item.total && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null ? (
{ item.total && 'token_id' in item.total && item.token && (NFT_TOKEN_TYPE_IDS.includes(item.token.type)) && item.total.token_id !== null ? (
<NftEntity
hash={ item.token.address }
id={ item.total.token_id }
......@@ -72,7 +72,7 @@ const TokenTransferTableItem = ({ item, isLoading }: Props) => {
) : '-' }
</Td>
<Td isNumeric verticalAlign="top">
{ valueStr ? (
{ (item.token && valueStr) ? (
<Flex gap={ 2 } overflow="hidden" justifyContent="flex-end">
<Skeleton isLoaded={ !isLoading } wordBreak="break-all">
{ valueStr }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment