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 {
tokenInfo: TokenInfo | 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 {
chartsMarket = 'charts-market',
indexBlocks='indexBlocks',
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 { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js';
import { useRouter } from 'next/router';
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 qrCodeIcon from 'icons/qr_code.svg';
import starOutlineIcon from 'icons/star_outline.svg';
import useFetch from 'lib/hooks/useFetch';
import AddressIcon from 'ui/shared/address/AddressIcon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
interface Props {
addressInfo: UseQueryResult<TAddress>;
addressQuery: UseQueryResult<TAddress>;
}
const AddressDetails = ({ addressInfo }: Props) => {
const { data, isError, isLoading } = addressInfo;
if (isError || isLoading) {
return null;
const AddressDetails = ({ addressQuery }: Props) => {
const router = useRouter();
const fetch = useFetch();
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 (
<Box>
<Flex alignItems="center">
<AddressIcon hash={ data.hash }/>
<Text ml={ 2 } fontFamily="heading" fontWeight={ 500 }>{ data.hash }</Text>
<CopyToClipboard text={ data.hash }/>
<AddressIcon hash={ addressQuery.data.hash }/>
<Text ml={ 2 } fontFamily="heading" fontWeight={ 500 }>{ addressQuery.data.hash }</Text>
<CopyToClipboard text={ addressQuery.data.hash }/>
<Icon as={ metamaskIcon } boxSize={ 6 } ml={ 2 }/>
<Button variant="outline" size="sm" ml={ 3 }>
<Icon as={ starOutlineIcon } boxSize={ 5 }/>
......@@ -34,6 +54,39 @@ const AddressDetails = ({ addressInfo }: Props) => {
<Icon as={ qrCodeIcon } boxSize={ 5 }/>
</Button>
</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>
);
};
......
......@@ -4,6 +4,7 @@ import { useRouter } from 'next/router';
import React from 'react';
import type { Address } from 'types/api/address';
import { QueryKeys } from 'types/client/queries';
import useFetch from 'lib/hooks/useFetch';
import AddressDetails from 'ui/address/AddressDetails';
......@@ -14,8 +15,8 @@ const AddressPageContent = () => {
const router = useRouter();
const fetch = useFetch();
const addressInfo = useQuery<unknown, unknown, Address>(
[ 'address', router.query.id ],
const addressQuery = useQuery<unknown, unknown, Address>(
[ QueryKeys.address, router.query.id ],
async() => await fetch(`/node-api/addresses/${ router.query.id }`),
{
enabled: Boolean(router.query.id),
......@@ -23,9 +24,9 @@ const AddressPageContent = () => {
);
const tags = [
...(addressInfo.data?.private_tags || []),
...(addressInfo.data?.public_tags || []),
...(addressInfo.data?.watchlist_names || []),
...(addressQuery.data?.private_tags || []),
...(addressQuery.data?.public_tags || []),
...(addressQuery.data?.watchlist_names || []),
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
return (
......@@ -38,7 +39,7 @@ const AddressPageContent = () => {
</Flex>
) }
</Flex>
<AddressDetails addressInfo={ addressInfo }/>
<AddressDetails addressQuery={ addressQuery }/>
</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