Skip to content

Commit

Permalink
remove token info from instance
Browse files Browse the repository at this point in the history
  • Loading branch information
ArminaAiren committed Nov 29, 2023
1 parent 3d3b251 commit f7aacab
Show file tree
Hide file tree
Showing 10 changed files with 63 additions and 38 deletions.
2 changes: 0 additions & 2 deletions mocks/tokens/tokenInstance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import type { TokenInstance } from 'types/api/token';

import * as addressMock from '../address/address';
import { tokenInfoERC721a } from './tokenInfo';

export const base: TokenInstance = {
animation_url: null,
Expand Down Expand Up @@ -74,7 +73,6 @@ export const base: TokenInstance = {
name: 'GENESIS #188848, 22a5f8bbb1602995. Blockchain pixel PFP NFT + "on music video" trait inspired by God',
},
owner: addressMock.withName,
token: tokenInfoERC721a,
};

export const withRichMetadata: TokenInstance = {
Expand Down
1 change: 0 additions & 1 deletion stubs/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,5 @@ export const TOKEN_INSTANCE: TokenInstance = {
name: 'GENESIS #188882, 8a77ca1bcaa4036f. Blockchain pixel PFP NFT + "on music video" trait inspired by God',
},
owner: ADDRESS_PARAMS,
token: TOKEN_INFO_ERC_1155,
holder_address_hash: ADDRESS_HASH,
};
1 change: 0 additions & 1 deletion types/api/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export interface TokenInstance {
external_app_url: string | null;
metadata: Record<string, unknown> | null;
owner: AddressParam | null;
token: TokenInfo;
}

export interface TokenInstanceTransfersCount {
Expand Down
2 changes: 1 addition & 1 deletion ui/pages/Token.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ const TokenPageContent = () => {

const tabs: Array<RoutedTab> = [
(tokenQuery.data?.type === 'ERC-1155' || tokenQuery.data?.type === 'ERC-721') ?
{ id: 'inventory', title: 'Inventory', component: <TokenInventory inventoryQuery={ inventoryQuery }/> } :
{ id: 'inventory', title: 'Inventory', component: <TokenInventory inventoryQuery={ inventoryQuery } tokenQuery={ tokenQuery }/> } :
undefined,
{ id: 'token_transfers', title: 'Token transfers', component: <TokenTransfer transfersQuery={ transfersQuery } token={ tokenQuery.data }/> },
{ id: 'holders', title: 'Holders', component: <TokenHolders token={ tokenQuery.data } holdersQuery={ holdersQuery }/> },
Expand Down
42 changes: 27 additions & 15 deletions ui/pages/TokenInstance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useAppContext } from 'lib/contexts/app';
import useIsMobile from 'lib/hooks/useIsMobile';
import * as metadata from 'lib/metadata';
import * as regexp from 'lib/regexp';
import { TOKEN_INSTANCE } from 'stubs/token';
import { TOKEN_INSTANCE, TOKEN_INFO_ERC_1155 } from 'stubs/token';
import * as tokenStubs from 'stubs/token';
import { generateListStub } from 'stubs/utils';
import AddressQrCode from 'ui/address/details/AddressQrCode';
Expand Down Expand Up @@ -43,6 +43,14 @@ const TokenInstanceContent = () => {

const scrollRef = React.useRef<HTMLDivElement>(null);

const tokenQuery = useApiQuery('token', {
pathParams: { hash },
queryOptions: {
enabled: Boolean(hash && id),
placeholderData: TOKEN_INFO_ERC_1155,
},
});

const tokenInstanceQuery = useApiQuery('token_instance', {
pathParams: { hash, id },
queryOptions: {
Expand All @@ -58,14 +66,18 @@ const TokenInstanceContent = () => {
options: {
enabled: Boolean(hash && id && (!tab || tab === 'token_transfers') && !tokenInstanceQuery.isPlaceholderData && tokenInstanceQuery.data),
placeholderData: generateListStub<'token_instance_transfers'>(
tokenInstanceQuery.data?.token.type === 'ERC-1155' ? tokenStubs.TOKEN_TRANSFER_ERC_1155 : tokenStubs.TOKEN_TRANSFER_ERC_721,
tokenQuery.data?.type === 'ERC-1155' ? tokenStubs.TOKEN_TRANSFER_ERC_1155 : tokenStubs.TOKEN_TRANSFER_ERC_721,
10,
{ next_page_params: null },
),
},
});

const shouldFetchHolders = !tokenInstanceQuery.isPlaceholderData && tokenInstanceQuery.data && !tokenInstanceQuery.data.is_unique;
const shouldFetchHolders =
!tokenQuery.isPlaceholderData &&
!tokenInstanceQuery.isPlaceholderData &&
tokenInstanceQuery.data &&
!tokenInstanceQuery.data.is_unique;

const holdersQuery = useQueryWithPages({
resourceName: 'token_instance_holders',
Expand All @@ -74,18 +86,18 @@ const TokenInstanceContent = () => {
options: {
enabled: Boolean(hash && tab === 'holders' && shouldFetchHolders),
placeholderData: generateListStub<'token_instance_holders'>(
tokenInstanceQuery.data?.token.type === 'ERC-1155' ? tokenStubs.TOKEN_HOLDER_ERC_1155 : tokenStubs.TOKEN_HOLDER_ERC_20, 10, { next_page_params: null }),
tokenQuery.data?.type === 'ERC-1155' ? tokenStubs.TOKEN_HOLDER_ERC_1155 : tokenStubs.TOKEN_HOLDER_ERC_20, 10, { next_page_params: null }),
},
});

React.useEffect(() => {
if (tokenInstanceQuery.data && !tokenInstanceQuery.isPlaceholderData) {
if (tokenInstanceQuery.data && !tokenInstanceQuery.isPlaceholderData && tokenQuery.data && !tokenQuery.isPlaceholderData) {
metadata.update(
{ pathname: '/token/[hash]/instance/[id]', query: { hash: tokenInstanceQuery.data.token.address, id: tokenInstanceQuery.data.id } },
{ symbol: tokenInstanceQuery.data.token.symbol ?? '' },
{ pathname: '/token/[hash]/instance/[id]', query: { hash: tokenQuery.data.address, id: tokenInstanceQuery.data.id } },
{ symbol: tokenQuery.data.symbol ?? '' },
);
}
}, [ tokenInstanceQuery.data, tokenInstanceQuery.isPlaceholderData ]);
}, [ tokenInstanceQuery.data, tokenInstanceQuery.isPlaceholderData, tokenQuery.data, tokenQuery.isPlaceholderData ]);

const backLink = React.useMemo(() => {
const hasGoBackLink = appProps.referrer && appProps.referrer.includes(`/token/${ hash }`) && !appProps.referrer.includes('instance');
Expand All @@ -104,10 +116,10 @@ const TokenInstanceContent = () => {
{
id: 'token_transfers',
title: 'Token transfers',
component: <TokenTransfer transfersQuery={ transfersQuery } tokenId={ id } token={ tokenInstanceQuery.data?.token }/>,
component: <TokenTransfer transfersQuery={ transfersQuery } tokenId={ id } token={ tokenQuery.data }/>,
},
shouldFetchHolders ?
{ id: 'holders', title: 'Holders', component: <TokenHolders holdersQuery={ holdersQuery } token={ tokenInstanceQuery.data?.token }/> } :
{ id: 'holders', title: 'Holders', component: <TokenHolders holdersQuery={ holdersQuery } token={ tokenQuery.data }/> } :
undefined,
{ id: 'metadata', title: 'Metadata', component: (
<TokenInstanceMetadata
Expand All @@ -121,7 +133,7 @@ const TokenInstanceContent = () => {
throw Error('Token instance fetch failed', { cause: tokenInstanceQuery.error });
}

const tokenTag = <Tag isLoading={ tokenInstanceQuery.isPlaceholderData }>{ tokenInstanceQuery.data?.token.type }</Tag>;
const tokenTag = <Tag isLoading={ tokenInstanceQuery.isPlaceholderData }>{ tokenQuery.data?.type }</Tag>;

const address = {
hash: hash || '',
Expand All @@ -131,7 +143,7 @@ const TokenInstanceContent = () => {
watchlist_address_id: null,
};

const isLoading = tokenInstanceQuery.isPlaceholderData;
const isLoading = tokenInstanceQuery.isPlaceholderData || tokenQuery.isPlaceholderData;

const appLink = (() => {
if (!tokenInstanceQuery.data?.external_app_url) {
Expand Down Expand Up @@ -168,7 +180,7 @@ const TokenInstanceContent = () => {
const titleSecondRow = (
<Flex alignItems="center" w="100%" minW={ 0 } columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}>
<TokenEntity
token={ tokenInstanceQuery.data?.token }
token={ tokenQuery.data }
isLoading={ isLoading }
noSymbol
noCopy
Expand All @@ -179,7 +191,7 @@ const TokenInstanceContent = () => {
w="auto"
maxW="700px"
/>
{ !isLoading && tokenInstanceQuery.data && <AddressAddToWallet token={ tokenInstanceQuery.data.token } variant="button"/> }
{ !isLoading && tokenInstanceQuery.data && <AddressAddToWallet token={ tokenQuery.data } variant="button"/> }
<AddressQrCode address={ address } isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading }/>
{ appLink }
Expand All @@ -197,7 +209,7 @@ const TokenInstanceContent = () => {
isLoading={ isLoading }
/>

<TokenInstanceDetails data={ tokenInstanceQuery?.data } isLoading={ isLoading } scrollRef={ scrollRef }/>
<TokenInstanceDetails data={ tokenInstanceQuery?.data } isLoading={ isLoading } scrollRef={ scrollRef } token={ tokenQuery.data }/>

{ /* should stay before tabs to scroll up with pagination */ }
<Box ref={ scrollRef }></Box>
Expand Down
6 changes: 6 additions & 0 deletions ui/token/TokenInventory.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Box } from '@chakra-ui/react';
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';

import { tokenInfoERC721a } from 'mocks/tokens/tokenInfo';
import { base as tokenInstanse } from 'mocks/tokens/tokenInstance';
import TestApp from 'playwright/TestApp';

Expand All @@ -23,6 +24,11 @@ test('base view +@mobile', async({ mount }) => {
// @ts-ignore:
pagination: { page: 1, isVisible: true },
}}
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore:
tokenQuery={{
data: tokenInfoERC721a,
}}
/>
</TestApp>,
);
Expand Down
15 changes: 11 additions & 4 deletions ui/token/TokenInventory.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react';

import type { TokenInfo } from 'types/api/token';

import type { ResourceError } from 'lib/api/resources';
import useIsMobile from 'lib/hooks/useIsMobile';
import ActionBar from 'ui/shared/ActionBar';
import DataListDisplay from 'ui/shared/DataListDisplay';
Expand All @@ -11,9 +15,10 @@ import TokenInventoryItem from './TokenInventoryItem';

type Props = {
inventoryQuery: QueryWithPagesResult<'token_inventory'>;
tokenQuery: UseQueryResult<TokenInfo, ResourceError<unknown>>;
}

const TokenInventory = ({ inventoryQuery }: Props) => {
const TokenInventory = ({ inventoryQuery, tokenQuery }: Props) => {
const isMobile = useIsMobile();

const actionBar = isMobile && inventoryQuery.pagination.isVisible && (
Expand All @@ -23,8 +28,9 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
);

const items = inventoryQuery.data?.items;
const token = tokenQuery.data;

const content = items ? (
const content = items && token ? (
<Grid
w="100%"
columnGap={{ base: 3, lg: 6 }}
Expand All @@ -33,9 +39,10 @@ const TokenInventory = ({ inventoryQuery }: Props) => {
>
{ items.map((item, index) => (
<TokenInventoryItem
key={ item.token.address + '_' + item.id + (inventoryQuery.isPlaceholderData ? '_' + index : '') }
key={ token.address + '_' + item.id + (inventoryQuery.isPlaceholderData ? '_' + index : '') }
item={ item }
isLoading={ inventoryQuery.isPlaceholderData }
isLoading={ inventoryQuery.isPlaceholderData || tokenQuery.isPlaceholderData }
token={ token }
/>
)) }
</Grid>
Expand Down
10 changes: 5 additions & 5 deletions ui/token/TokenInventoryItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Box, Flex, Text, Link, useColorModeValue, Skeleton } from '@chakra-ui/react';
import React from 'react';

import type { TokenInstance } from 'types/api/token';
import type { TokenInfo, TokenInstance } from 'types/api/token';

import { route } from 'nextjs-routes';

Expand All @@ -11,9 +11,9 @@ import LinkInternal from 'ui/shared/LinkInternal';
import NftMedia from 'ui/shared/nft/NftMedia';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';

type Props = { item: TokenInstance; isLoading: boolean };
type Props = { item: TokenInstance; token: TokenInfo; isLoading: boolean };

const NFTItem = ({ item, isLoading }: Props) => {
const TokenInventoryItem = ({ item, token, isLoading }: Props) => {

const isMobile = useIsMobile();

Expand All @@ -25,7 +25,7 @@ const NFTItem = ({ item, isLoading }: Props) => {
/>
);

const url = route({ pathname: '/token/[hash]/instance/[id]', query: { hash: item.token.address, id: item.id } });
const url = route({ pathname: '/token/[hash]/instance/[id]', query: { hash: token.address, id: item.id } });

return (
<Box
Expand Down Expand Up @@ -76,4 +76,4 @@ const NFTItem = ({ item, isLoading }: Props) => {
);
};

export default NFTItem;
export default TokenInventoryItem;
9 changes: 6 additions & 3 deletions ui/tokenInstance/TokenInstanceDetails.pw.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';

import * as addressMock from 'mocks/address/address';
import { tokenInfoERC721a } from 'mocks/tokens/tokenInfo';
import * as tokenInstanceMock from 'mocks/tokens/tokenInstance';
import TestApp from 'playwright/TestApp';
import buildApiUrl from 'playwright/utils/buildApiUrl';
import * as configs from 'playwright/utils/configs';

import TokenInstanceDetails from './TokenInstanceDetails';

const API_URL_ADDRESS = buildApiUrl('address', { hash: tokenInstanceMock.base.token.address });
const hash = tokenInfoERC721a.address;

const API_URL_ADDRESS = buildApiUrl('address', { hash });
const API_URL_TOKEN_TRANSFERS_COUNT = buildApiUrl('token_instance_transfers_count', {
id: tokenInstanceMock.unique.id,
hash: tokenInstanceMock.unique.token.address,
hash,
});

test('base view +@dark-mode +@mobile', async({ mount, page }) => {
Expand All @@ -31,7 +34,7 @@ test('base view +@dark-mode +@mobile', async({ mount, page }) => {

const component = await mount(
<TestApp>
<TokenInstanceDetails data={ tokenInstanceMock.unique }/>
<TokenInstanceDetails data={ tokenInstanceMock.unique } token={ tokenInfoERC721a }/>
</TestApp>,
);

Expand Down
13 changes: 7 additions & 6 deletions ui/tokenInstance/TokenInstanceDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Flex, Grid, Skeleton } from '@chakra-ui/react';
import React from 'react';

import type { TokenInstance } from 'types/api/token';
import type { TokenInfo, TokenInstance } from 'types/api/token';

import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
Expand All @@ -18,19 +18,20 @@ import TokenInstanceTransfersCount from './details/TokenInstanceTransfersCount';

interface Props {
data?: TokenInstance;
token?: TokenInfo;
isLoading?: boolean;
scrollRef?: React.RefObject<HTMLDivElement>;
}

const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => {
const TokenInstanceDetails = ({ data, token, scrollRef, isLoading }: Props) => {
const handleCounterItemClick = React.useCallback(() => {
window.setTimeout(() => {
// cannot do scroll instantly, have to wait a little
scrollRef?.current?.scrollIntoView({ behavior: 'smooth' });
}, 500);
}, [ scrollRef ]);

if (!data) {
if (!data || !token) {
return null;
}

Expand All @@ -56,7 +57,7 @@ const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => {
/>
</DetailsInfoItem>
) }
<TokenInstanceCreatorAddress hash={ isLoading ? '' : data.token.address }/>
<TokenInstanceCreatorAddress hash={ isLoading ? '' : token.address }/>
<DetailsInfoItem
title="Token ID"
hint="This token instance unique token ID"
Expand All @@ -69,8 +70,8 @@ const TokenInstanceDetails = ({ data, scrollRef, isLoading }: Props) => {
<CopyToClipboard text={ data.id } isLoading={ isLoading }/>
</Flex>
</DetailsInfoItem>
<TokenInstanceTransfersCount hash={ isLoading ? '' : data.token.address } id={ isLoading ? '' : data.id } onClick={ handleCounterItemClick }/>
<TokenNftMarketplaces isLoading={ isLoading } hash={ data.token.address } id={ data.id }/>
<TokenInstanceTransfersCount hash={ isLoading ? '' : token.address } id={ isLoading ? '' : data.id } onClick={ handleCounterItemClick }/>
<TokenNftMarketplaces isLoading={ isLoading } hash={ token.address } id={ data.id }/>
</Grid>
<NftMedia
url={ data.animation_url || data.image_url }
Expand Down

0 comments on commit f7aacab

Please sign in to comment.