diff --git a/mocks/tokens/tokenTransfer.ts b/mocks/tokens/tokenTransfer.ts index 9638bcc885..f17da56ec4 100644 --- a/mocks/tokens/tokenTransfer.ts +++ b/mocks/tokens/tokenTransfer.ts @@ -1,3 +1,4 @@ +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', }, diff --git a/types/api/tokenTransfer.ts b/types/api/tokenTransfer.ts index 90b74d8034..b34b78269a 100644 --- a/types/api/tokenTransfer.ts +++ b/types/api/tokenTransfer.ts @@ -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; diff --git a/ui/address/AddressTokenTransfers.tsx b/ui/address/AddressTokenTransfers.tsx index 7d336b4fc0..077dc25b47 100644 --- a/ui/address/AddressTokenTransfers.tsx +++ b/ui/address/AddressTokenTransfers.tsx @@ -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; } } diff --git a/ui/pages/Token.tsx b/ui/pages/Token.tsx index 9c3fc28b88..8b2685bc04 100644 --- a/ui/pages/Token.tsx +++ b/ui/pages/Token.tsx @@ -170,7 +170,7 @@ const TokenPageContent = () => { { id: 'token_transfers', title: 'Token transfers', - component: , + component: , }, { id: 'holders', diff --git a/ui/pages/TokenInstance.tsx b/ui/pages/TokenInstance.tsx index 62e70f62c3..6391bff737 100644 --- a/ui/pages/TokenInstance.tsx +++ b/ui/pages/TokenInstance.tsx @@ -97,7 +97,7 @@ const TokenInstanceContent = () => { { id: 'token_transfers', title: 'Token transfers', - component: , + component: , }, shouldFetchHolders ? { id: 'holders', title: 'Holders', component: } : diff --git a/ui/shared/TokenTransfer/TokenTransferListItem.tsx b/ui/shared/TokenTransfer/TokenTransferListItem.tsx index d26019f156..2fc519d2df 100644 --- a/ui/shared/TokenTransfer/TokenTransferListItem.tsx +++ b/ui/shared/TokenTransfer/TokenTransferListItem.tsx @@ -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 = ({ - - { getTokenTypeName(token.type) } + { token && ( + <> + + { getTokenTypeName(token.type) } + + ) } { getTokenTransferTypeText(type) } { showTxInfo && txHash && ( ) } - { total && 'token_id' in total && total.token_id !== null && } + { total && 'token_id' in total && total.token_id !== null && token && ( + + ) } { showTxInfo && txHash && ( { 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 = ({ ) } - - - { getTokenTypeName(token.type) } - { getTokenTransferTypeText(type) } - + { token ? ( + <> + + + { getTokenTypeName(token.type) } + { getTokenTransferTypeText(type) } + + + ) : 'N/A' } - { total && 'token_id' in total && total.token_id !== null && } + { total && 'token_id' in total && total.token_id !== null && token && ( + + ) } { showTxInfo && txHash && ( diff --git a/ui/shared/TokenTransferSnippet/TokenTransferSnippet.tsx b/ui/shared/TokenTransferSnippet/TokenTransferSnippet.tsx index 26cfc8f836..f62498d5d5 100644 --- a/ui/shared/TokenTransferSnippet/TokenTransferSnippet.tsx +++ b/ui/shared/TokenTransferSnippet/TokenTransferSnippet.tsx @@ -28,7 +28,7 @@ const TokenTransferSnippet = ({ data, isLoading, noAddressIcons = true }: Props) return ; } - 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 ; } } + default: { + return null; + } } })(); diff --git a/ui/token/TokenTransfer/TokenTransfer.pw.tsx b/ui/token/TokenTransfer/TokenTransfer.pw.tsx index 47544a5fde..421452e3ac 100644 --- a/ui/token/TokenTransfer/TokenTransfer.pw.tsx +++ b/ui/token/TokenTransfer/TokenTransfer.pw.tsx @@ -1,6 +1,7 @@ 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, + }} /> , ); @@ -43,6 +48,10 @@ test('erc721 +@mobile', async({ render }) => { // @ts-ignore: pagination: { page: 1, isVisible: true }, }} + // @ts-ignore: + tokenQuery={{ + data: tokenInfoERC721a, + }} /> , ); @@ -70,6 +79,10 @@ test('erc1155 +@mobile', async({ render }) => { // @ts-ignore: pagination: { page: 1, isVisible: true }, }} + // @ts-ignore: + tokenQuery={{ + data: tokenInfoERC1155a, + }} /> , ); diff --git a/ui/token/TokenTransfer/TokenTransfer.tsx b/ui/token/TokenTransfer/TokenTransfer.tsx index 76e19e8cbd..e85b874118 100644 --- a/ui/token/TokenTransfer/TokenTransfer.tsx +++ b/ui/token/TokenTransfer/TokenTransfer.tsx @@ -1,10 +1,12 @@ 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>; 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 ? ( <> @@ -85,10 +90,10 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }: num={ newItemsCount } alert={ socketAlert } type="token_transfer" - isLoading={ isPlaceholderData } + isLoading={ isLoading } /> ) } - + ) : null; @@ -101,7 +106,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, token, shouldRender = true }: return ( { 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') && ( Value @@ -89,7 +89,7 @@ const TokenTransferListItem = ({ ) } ) } - { 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 && ( { - const tokenType = data[0].token.type; + + const tokenType = token.type; return ( diff --git a/ui/token/TokenTransfer/TokenTransferTableItem.tsx b/ui/token/TokenTransfer/TokenTransferTableItem.tsx index 99010a1098..216df530c1 100644 --- a/ui/token/TokenTransfer/TokenTransferTableItem.tsx +++ b/ui/token/TokenTransfer/TokenTransferTableItem.tsx @@ -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 } /> - { (NFT_TOKEN_TYPE_IDS.includes(token.type)) && ( + { (token && NFT_TOKEN_TYPE_IDS.includes(token.type)) && ( - { total && 'token_id' in total && total.token_id !== null ? ( + { total && 'token_id' in total && token && total.token_id !== null ? ( ) } - { (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') && ( { valueStr && ( diff --git a/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc1155-mobile-1.png b/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc1155-mobile-1.png index 907602b9e6..da7c02bead 100644 Binary files a/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc1155-mobile-1.png and b/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc1155-mobile-1.png differ diff --git a/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc20-mobile-1.png b/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc20-mobile-1.png index f3676476c5..086f108072 100644 Binary files a/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc20-mobile-1.png and b/ui/token/TokenTransfer/__screenshots__/TokenTransfer.pw.tsx_default_erc20-mobile-1.png differ diff --git a/ui/tokenTransfers/TokenTransfersListItem.tsx b/ui/tokenTransfers/TokenTransfersListItem.tsx index 305813fc4b..64a7814f95 100644 --- a/ui/tokenTransfers/TokenTransfersListItem.tsx +++ b/ui/tokenTransfers/TokenTransfersListItem.tsx @@ -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) => { - { 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 && ( <> Token ID @@ -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') && ( <> Amount diff --git a/ui/tokenTransfers/TokenTransfersTableItem.tsx b/ui/tokenTransfers/TokenTransfersTableItem.tsx index c9897ed43c..7a1251329f 100644 --- a/ui/tokenTransfers/TokenTransfersTableItem.tsx +++ b/ui/tokenTransfers/TokenTransfersTableItem.tsx @@ -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) => { /> - { 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 ? ( { ) : '-' } - { valueStr ? ( + { (item.token && valueStr) ? ( { valueStr }