Commit 98efbf80 authored by tom's avatar tom

main details

parent 3114ef88
...@@ -25,7 +25,7 @@ import type { RawTracesResponse } from 'types/api/rawTrace'; ...@@ -25,7 +25,7 @@ import type { RawTracesResponse } from 'types/api/rawTrace';
import type { SearchResult, SearchResultFilters } from 'types/api/search'; import type { SearchResult, SearchResultFilters } from 'types/api/search';
import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats'; import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats';
import type { TokenCounters, TokenInfo, TokenHolders } from 'types/api/tokenInfo'; import type { TokenCounters, TokenInfo, TokenHolders } from 'types/api/tokenInfo';
import type { TokensResponse, TokensFilters, TokenInstance } from 'types/api/tokens'; import type { TokensResponse, TokensFilters, TokenInstance, TokenInstanceTransfersCount } from 'types/api/tokens';
import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer'; import type { TokenTransferResponse, TokenTransferFilters } from 'types/api/tokenTransfer';
import type { TransactionsResponseValidated, TransactionsResponsePending, Transaction } from 'types/api/transaction'; import type { TransactionsResponseValidated, TransactionsResponsePending, Transaction } from 'types/api/transaction';
import type { TTxsFilters } from 'types/api/txsFilters'; import type { TTxsFilters } from 'types/api/txsFilters';
...@@ -240,6 +240,9 @@ export const RESOURCES = { ...@@ -240,6 +240,9 @@ export const RESOURCES = {
token_instance: { token_instance: {
path: '/api/v2/tokens/:hash/instances/:id', path: '/api/v2/tokens/:hash/instances/:id',
}, },
token_instance_transfers_count: {
path: '/api/v2/tokens/:hash/instances/:id/transfers-count',
},
// HOMEPAGE // HOMEPAGE
homepage_stats: { homepage_stats: {
...@@ -363,6 +366,7 @@ Q extends 'token_counters' ? TokenCounters : ...@@ -363,6 +366,7 @@ Q extends 'token_counters' ? TokenCounters :
Q extends 'token_transfers' ? TokenTransferResponse : Q extends 'token_transfers' ? TokenTransferResponse :
Q extends 'token_holders' ? TokenHolders : Q extends 'token_holders' ? TokenHolders :
Q extends 'token_instance' ? TokenInstance : Q extends 'token_instance' ? TokenInstance :
Q extends 'token_instance_transfers_count' ? TokenInstanceTransfersCount :
Q extends 'tokens' ? TokensResponse : Q extends 'tokens' ? TokensResponse :
Q extends 'search' ? SearchResult : Q extends 'search' ? SearchResult :
Q extends 'contract' ? SmartContract : Q extends 'contract' ? SmartContract :
......
...@@ -23,3 +23,7 @@ export interface TokenInstance { ...@@ -23,3 +23,7 @@ export interface TokenInstance {
owner: AddressParam; owner: AddressParam;
token: TokenInfo; token: TokenInfo;
} }
export interface TokenInstanceTransfersCount {
transfers_count: number;
}
...@@ -15,6 +15,7 @@ import Page from 'ui/shared/Page/Page'; ...@@ -15,6 +15,7 @@ import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs'; import RoutedTabs from 'ui/shared/RoutedTabs/RoutedTabs';
import TokenLogo from 'ui/shared/TokenLogo'; import TokenLogo from 'ui/shared/TokenLogo';
import TokenInstanceDetails from 'ui/tokenInstance/TokenInstanceDetails';
export type TokenTabs = 'token_transfers' | 'holders' export type TokenTabs = 'token_transfers' | 'holders'
...@@ -77,6 +78,8 @@ const TokenInstance = () => { ...@@ -77,6 +78,8 @@ const TokenInstance = () => {
<AddressHeadingInfo address={ address } token={ tokenInstanceQuery.data.token }/> <AddressHeadingInfo address={ address } token={ tokenInstanceQuery.data.token }/>
<TokenInstanceDetails data={ tokenInstanceQuery.data } scrollRef={ scrollRef }/>
<AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/> <AdBanner mt={{ base: 6, lg: 8 }} justifyContent="center"/>
{ /* should stay before tabs to scroll up with pagination */ } { /* should stay before tabs to scroll up with pagination */ }
......
import { Box, Flex, Grid } from '@chakra-ui/react';
import React from 'react';
import type { TokenInstance } from 'types/api/tokens';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
import TokenInstanceCreatorAddress from './details/TokenInstanceCreatorAddress';
import TokenInstanceTransfersCount from './details/TokenInstanceTransfersCount';
interface Props {
data: TokenInstance;
scrollRef?: React.RefObject<HTMLDivElement>;
}
const TokenInstanceDetails = ({ data, scrollRef }: Props) => {
const handleCounterItemClick = React.useCallback(() => {
window.setTimeout(() => {
// cannot do scroll instantly, have to wait a little
scrollRef?.current?.scrollIntoView({ behavior: 'smooth' });
}, 500);
}, [ scrollRef ]);
return (
<Flex alignItems="flex-start" mt={ 8 } flexDir={{ base: 'column', lg: 'row' }} columnGap={ 6 } rowGap={ 6 }>
<Grid
flexGrow={ 1 }
columnGap={ 8 }
rowGap={{ base: 1, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: '200px minmax(0, 1fr)' }} overflow="hidden"
>
<DetailsInfoItem
title="Token"
hint="Token name."
>
<TokenSnippet hash={ data.token.address } name={ data.token.name }/>
</DetailsInfoItem>
<DetailsInfoItem
title="Owner"
hint="Current owner of this token instance."
>
<Address>
<AddressIcon address={ data.owner }/>
<AddressLink type="address" hash={ data.owner.hash } ml={ 2 }/>
<CopyToClipboard text={ data.owner.hash }/>
</Address>
</DetailsInfoItem>
<TokenInstanceCreatorAddress hash={ data.token.address }/>
<DetailsInfoItem
title="Token ID"
hint="This token instance unique token ID."
>
{ data.id }
<CopyToClipboard text={ data.id } ml={ 1 }/>
</DetailsInfoItem>
<DetailsInfoItem
title="Quantity"
hint="Current quantity of this token instance."
>
1
</DetailsInfoItem>
<TokenInstanceTransfersCount hash={ data.token.address } id={ data.id } onClick={ handleCounterItemClick }/>
</Grid>
<Box boxSize="250px" bgColor="lightpink" flexShrink={ 0 }/>
</Flex>
);
};
export default React.memo(TokenInstanceDetails);
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSkeletonRow from 'ui/shared/skeletons/DetailsSkeletonRow';
interface Props {
hash: string;
}
const TokenInstanceCreatorAddress = ({ hash }: Props) => {
const addressQuery = useApiQuery('address', {
pathParams: { id: hash },
});
if (addressQuery.isError) {
return null;
}
if (addressQuery.isLoading) {
return <DetailsSkeletonRow w="30%"/>;
}
if (!addressQuery.data.creator_address_hash) {
return null;
}
const creatorAddress = {
hash: addressQuery.data.creator_address_hash,
is_contract: false,
implementation_name: null,
};
return (
<DetailsInfoItem
title="Creator"
hint="Address that deployed this token contract"
>
<Address>
<AddressIcon address={ creatorAddress }/>
<AddressLink type="address" hash={ creatorAddress.hash } ml={ 2 }/>
<CopyToClipboard text={ creatorAddress.hash }/>
</Address>
</DetailsInfoItem>
);
};
export default TokenInstanceCreatorAddress;
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import link from 'lib/link/link';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import LinkInternal from 'ui/shared/LinkInternal';
import DetailsSkeletonRow from 'ui/shared/skeletons/DetailsSkeletonRow';
interface Props {
hash: string;
id: string;
onClick: () => void;
}
const TokenInstanceTransfersCount = ({ hash, id, onClick }: Props) => {
const transfersCountQuery = useApiQuery('token_instance_transfers_count', {
pathParams: { hash, id },
});
if (transfersCountQuery.isError) {
return null;
}
if (transfersCountQuery.isLoading) {
return <DetailsSkeletonRow w="30%"/>;
}
if (!transfersCountQuery.data.transfers_count) {
return null;
}
const url = transfersCountQuery.data.transfers_count > 0 ?
link('token_instance_item', { id, hash }, { tab: 'token_transfers' }) :
undefined;
return (
<DetailsInfoItem
title="Transfers"
hint="Number of transfer for the token instance."
>
<LinkInternal
href={ url }
onClick={ transfersCountQuery.data.transfers_count > 0 ? onClick : undefined }
>
{ transfersCountQuery.data.transfers_count }
</LinkInternal>
</DetailsInfoItem>
);
};
export default TokenInstanceTransfersCount;
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