Commit d6f80acd authored by tom's avatar tom

address counters

parent 4523797f
import type { NextApiRequest } from 'next';
import handler from 'lib/api/handler';
const getUrl = (req: NextApiRequest) => {
return `/v2/addresses/${ req.query.id }/counters`;
};
const requestHandler = handler(getUrl, [ 'GET' ]);
export default requestHandler;
...@@ -18,3 +18,10 @@ export interface Address { ...@@ -18,3 +18,10 @@ export interface Address {
tokenInfo: TokenInfo | null; tokenInfo: TokenInfo | null;
watchlist_names: Array<WatchlistName> | null; watchlist_names: Array<WatchlistName> | null;
} }
export interface AddressCounters {
transaction_count: string;
token_transfer_count: string;
gas_usage_count: string;
validation_count: string | null;
}
...@@ -16,5 +16,7 @@ export enum QueryKeys { ...@@ -16,5 +16,7 @@ export enum QueryKeys {
chartsMarket = 'charts-market', chartsMarket = 'charts-market',
indexBlocks='indexBlocks', indexBlocks='indexBlocks',
indexTxs='indexTxs', indexTxs='indexTxs',
jsonRpcUrl='json-rpc-url' jsonRpcUrl='json-rpc-url',
address='address',
addressCounters='address-counters',
} }
import { Box, Flex, Text, Icon, Button } from '@chakra-ui/react'; import { Box, Flex, Text, Icon, Button, Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js';
import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Address as TAddress } from 'types/api/address'; import type { Address as TAddress, AddressCounters } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import metamaskIcon from 'icons/metamask.svg'; import metamaskIcon from 'icons/metamask.svg';
import qrCodeIcon from 'icons/qr_code.svg'; import qrCodeIcon from 'icons/qr_code.svg';
import starOutlineIcon from 'icons/star_outline.svg'; import starOutlineIcon from 'icons/star_outline.svg';
import useFetch from 'lib/hooks/useFetch';
import AddressIcon from 'ui/shared/address/AddressIcon'; import AddressIcon from 'ui/shared/address/AddressIcon';
import CopyToClipboard from 'ui/shared/CopyToClipboard'; import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
interface Props { interface Props {
addressInfo: UseQueryResult<TAddress>; addressQuery: UseQueryResult<TAddress>;
} }
const AddressDetails = ({ addressInfo }: Props) => { const AddressDetails = ({ addressQuery }: Props) => {
const { data, isError, isLoading } = addressInfo; const router = useRouter();
if (isError || isLoading) { const fetch = useFetch();
return null;
const countersQuery = useQuery<unknown, unknown, AddressCounters>(
[ QueryKeys.addressCounters, router.query.id ],
async() => await fetch(`/node-api/addresses/${ router.query.id }/counters`),
{
enabled: Boolean(router.query.id) && Boolean(addressQuery.data),
},
);
if (countersQuery.isLoading || addressQuery.isLoading) {
return <Box>loading</Box>;
}
if (countersQuery.isError || addressQuery.isError) {
return <Box>error</Box>;
} }
return ( return (
<Box> <Box>
<Flex alignItems="center"> <Flex alignItems="center">
<AddressIcon hash={ data.hash }/> <AddressIcon hash={ addressQuery.data.hash }/>
<Text ml={ 2 } fontFamily="heading" fontWeight={ 500 }>{ data.hash }</Text> <Text ml={ 2 } fontFamily="heading" fontWeight={ 500 }>{ addressQuery.data.hash }</Text>
<CopyToClipboard text={ data.hash }/> <CopyToClipboard text={ addressQuery.data.hash }/>
<Icon as={ metamaskIcon } boxSize={ 6 } ml={ 2 }/> <Icon as={ metamaskIcon } boxSize={ 6 } ml={ 2 }/>
<Button variant="outline" size="sm" ml={ 3 }> <Button variant="outline" size="sm" ml={ 3 }>
<Icon as={ starOutlineIcon } boxSize={ 5 }/> <Icon as={ starOutlineIcon } boxSize={ 5 }/>
...@@ -34,6 +54,39 @@ const AddressDetails = ({ addressInfo }: Props) => { ...@@ -34,6 +54,39 @@ const AddressDetails = ({ addressInfo }: Props) => {
<Icon as={ qrCodeIcon } boxSize={ 5 }/> <Icon as={ qrCodeIcon } boxSize={ 5 }/>
</Button> </Button>
</Flex> </Flex>
<Grid
mt={ 8 }
columnGap={ 8 }
rowGap={{ base: 3, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden"
>
<DetailsInfoItem
title="Transactions"
hint="Number of transactions related to this address."
>
{ Number(countersQuery.data.transaction_count).toLocaleString() }
</DetailsInfoItem>
<DetailsInfoItem
title="Transfers"
hint="Number of transfers to/from this address."
>
{ Number(countersQuery.data.token_transfer_count).toLocaleString() }
</DetailsInfoItem>
<DetailsInfoItem
title="Gas used"
hint="Gas used by the address."
>
{ BigNumber(countersQuery.data.gas_usage_count).toFormat() }
</DetailsInfoItem>
{ countersQuery.data.validation_count && (
<DetailsInfoItem
title="Blocks validated"
hint="Number of blocks validated by this validator."
>
{ Number(countersQuery.data.validation_count).toLocaleString() }
</DetailsInfoItem>
) }
</Grid>
</Box> </Box>
); );
}; };
......
...@@ -4,6 +4,7 @@ import { useRouter } from 'next/router'; ...@@ -4,6 +4,7 @@ import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
import AddressDetails from 'ui/address/AddressDetails'; import AddressDetails from 'ui/address/AddressDetails';
...@@ -14,8 +15,8 @@ const AddressPageContent = () => { ...@@ -14,8 +15,8 @@ const AddressPageContent = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch(); const fetch = useFetch();
const addressInfo = useQuery<unknown, unknown, Address>( const addressQuery = useQuery<unknown, unknown, Address>(
[ 'address', router.query.id ], [ QueryKeys.address, router.query.id ],
async() => await fetch(`/node-api/addresses/${ router.query.id }`), async() => await fetch(`/node-api/addresses/${ router.query.id }`),
{ {
enabled: Boolean(router.query.id), enabled: Boolean(router.query.id),
...@@ -23,9 +24,9 @@ const AddressPageContent = () => { ...@@ -23,9 +24,9 @@ const AddressPageContent = () => {
); );
const tags = [ const tags = [
...(addressInfo.data?.private_tags || []), ...(addressQuery.data?.private_tags || []),
...(addressInfo.data?.public_tags || []), ...(addressQuery.data?.public_tags || []),
...(addressInfo.data?.watchlist_names || []), ...(addressQuery.data?.watchlist_names || []),
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>); ].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
return ( return (
...@@ -38,7 +39,7 @@ const AddressPageContent = () => { ...@@ -38,7 +39,7 @@ const AddressPageContent = () => {
</Flex> </Flex>
) } ) }
</Flex> </Flex>
<AddressDetails addressInfo={ addressInfo }/> <AddressDetails addressQuery={ addressQuery }/>
</Page> </Page>
); );
}; };
......
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