Commit 4ba45ecf authored by tom's avatar tom

tx tags

parent 6888a436
export interface Tag {
label: string;
display_name: string;
}
export interface AddressParam { export interface AddressParam {
hash: string; hash: string;
implementation_name: string; implementation_name: string;
name: string | null; name: string | null;
is_contract: boolean; is_contract: boolean;
private_tags: Array<string> | null; private_tags: Array<Tag> | null;
watchlist_names: Array<string> | null; watchlist_names: Array<Tag> | null;
public_tags: Array<string> | null; public_tags: Array<Tag> | null;
} }
...@@ -38,6 +38,7 @@ export interface Transaction { ...@@ -38,6 +38,7 @@ export interface Transaction {
token_transfers: Array<TokenTransfer> | null; token_transfers: Array<TokenTransfer> | null;
token_transfers_overflow: boolean; token_transfers_overflow: boolean;
exchange_rate: string; exchange_rate: string;
tx_tag: string | null;
} }
export interface TransactionsResponse { export interface TransactionsResponse {
......
import { Flex, Link, Icon } from '@chakra-ui/react'; import { Flex, Link, Icon, Tag } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
import type { Transaction } from 'types/api/transaction';
import type { RoutedTab } from 'ui/shared/RoutedTabs/types'; import type { RoutedTab } from 'ui/shared/RoutedTabs/types';
import eastArrowIcon from 'icons/arrows/east.svg'; import eastArrowIcon from 'icons/arrows/east.svg';
import useFetch from 'lib/hooks/useFetch';
import link from 'lib/link/link'; import link from 'lib/link/link';
import networkExplorers from 'lib/networks/networkExplorers'; import networkExplorers from 'lib/networks/networkExplorers';
import ExternalLink from 'ui/shared/ExternalLink'; import ExternalLink from 'ui/shared/ExternalLink';
...@@ -28,6 +31,15 @@ const TABS: Array<RoutedTab> = [ ...@@ -28,6 +31,15 @@ const TABS: Array<RoutedTab> = [
const TransactionPageContent = () => { const TransactionPageContent = () => {
const router = useRouter(); const router = useRouter();
const fetch = useFetch();
const { data } = useQuery<unknown, unknown, Transaction>(
[ 'tx', router.query.id ],
async() => await fetch(`/api/transactions/${ router.query.id }`),
{
enabled: Boolean(router.query.id),
},
);
const explorersLinks = networkExplorers const explorersLinks = networkExplorers
.filter((explorer) => explorer.paths.tx) .filter((explorer) => explorer.paths.tx)
...@@ -45,6 +57,7 @@ const TransactionPageContent = () => { ...@@ -45,6 +57,7 @@ const TransactionPageContent = () => {
</Link> </Link>
<Flex alignItems="flex-start" flexDir={{ base: 'column', lg: 'row' }}> <Flex alignItems="flex-start" flexDir={{ base: 'column', lg: 'row' }}>
<PageTitle text="Transaction details"/> <PageTitle text="Transaction details"/>
{ data?.tx_tag && <Tag my={ 2 } ml={ 3 }>{ data.tx_tag }</Tag> }
{ explorersLinks.length > 0 && ( { explorersLinks.length > 0 && (
<Flex <Flex
alignItems="center" alignItems="center"
......
...@@ -3,6 +3,7 @@ import React from 'react'; ...@@ -3,6 +3,7 @@ import React from 'react';
import nftIcon from 'icons/nft_shield.svg'; import nftIcon from 'icons/nft_shield.svg';
import link from 'lib/link/link'; import link from 'lib/link/link';
import AddressLink from 'ui/shared/address/AddressLink';
import TokenSnippet from 'ui/shared/TokenSnippet'; import TokenSnippet from 'ui/shared/TokenSnippet';
interface Props { interface Props {
...@@ -13,18 +14,22 @@ interface Props { ...@@ -13,18 +14,22 @@ interface Props {
symbol?: string | null; symbol?: string | null;
} }
const NftTokenTransferSnippet = (props: Props) => { const NftTokenTransferSnippet = ({ value, name, hash, symbol, tokenId }: Props) => {
const num = props.value === '1' ? '' : props.value; const num = value === '1' ? '' : value;
const url = link('token_instance_item', { hash: props.hash, id: props.tokenId }); const url = link('token_instance_item', { hash: hash, id: tokenId });
return ( return (
<Flex alignItems="center" columnGap={ 3 } rowGap={ 2 } flexWrap="wrap"> <Flex alignItems="center" columnGap={ 3 } rowGap={ 2 } flexWrap="wrap">
<Text fontWeight={ 500 } as="span">For { num } token ID:</Text> <Text fontWeight={ 500 } as="span">For { num } token ID:</Text>
<Box display="inline-flex" alignItems="center"> <Box display="inline-flex" alignItems="center">
<Icon as={ nftIcon } boxSize={ 6 } mr={ 1 }/> <Icon as={ nftIcon } boxSize={ 6 } mr={ 1 }/>
<Link href={ url } fontWeight={ 600 }>{ props.tokenId }</Link> <Link href={ url } fontWeight={ 600 }>{ tokenId }</Link>
</Box> </Box>
<TokenSnippet symbol={ props.symbol } hash={ props.hash } name={ props.name }/> { name ? (
<TokenSnippet symbol={ symbol } hash={ hash } name={ name }/>
) : (
<AddressLink hash={ hash } truncation="constant" type="token"/>
) }
</Flex> </Flex>
); );
}; };
......
import { Grid, GridItem, Text, Box, Icon, Link, Spinner } from '@chakra-ui/react'; import { Grid, GridItem, Text, Box, Icon, Link, Spinner, Tag, Flex, Tooltip, chakra } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
...@@ -10,9 +10,9 @@ import type { Transaction } from 'types/api/transaction'; ...@@ -10,9 +10,9 @@ import type { Transaction } from 'types/api/transaction';
import appConfig from 'configs/app/config'; import appConfig from 'configs/app/config';
import clockIcon from 'icons/clock.svg'; import clockIcon from 'icons/clock.svg';
import flameIcon from 'icons/flame.svg'; import flameIcon from 'icons/flame.svg';
import errorIcon from 'icons/status/error.svg';
import successIcon from 'icons/status/success.svg';
import { WEI, WEI_IN_GWEI } from 'lib/consts'; import { WEI, WEI_IN_GWEI } from 'lib/consts';
// import errorIcon from 'icons/status/error.svg';
// import successIcon from 'icons/status/success.svg';
import dayjs from 'lib/date/dayjs'; import dayjs from 'lib/date/dayjs';
import useFetch from 'lib/hooks/useFetch'; import useFetch from 'lib/hooks/useFetch';
import getConfirmationDuration from 'lib/tx/getConfirmationDuration'; import getConfirmationDuration from 'lib/tx/getConfirmationDuration';
...@@ -72,6 +72,18 @@ const TxDetails = () => { ...@@ -72,6 +72,18 @@ const TxDetails = () => {
return <DataFetchAlert/>; return <DataFetchAlert/>;
} }
const addressFromTags = [
...data.from.private_tags || [],
...data.from.public_tags || [],
...data.from.watchlist_names || [],
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
const addressToTags = [
...data.to.private_tags || [],
...data.to.public_tags || [],
...data.to.watchlist_names || [],
].map((tag) => <Tag key={ tag.label }>{ tag.display_name }</Tag>);
return ( return (
<Grid columnGap={ 8 } rowGap={{ base: 3, lg: 3 }} templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }}> <Grid columnGap={ 8 } rowGap={{ base: 3, lg: 3 }} templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }}>
<DetailsInfoItem <DetailsInfoItem
...@@ -131,12 +143,18 @@ const TxDetails = () => { ...@@ -131,12 +143,18 @@ const TxDetails = () => {
<DetailsInfoItem <DetailsInfoItem
title="From" title="From"
hint="Address (external or contract) sending the transaction." hint="Address (external or contract) sending the transaction."
columnGap={ 3 }
> >
<Address> <Address>
<AddressIcon hash={ data.from.hash }/> <AddressIcon hash={ data.from.hash }/>
<AddressLink ml={ 2 } hash={ data.from.hash } alias={ data.from.name }/> <AddressLink ml={ 2 } hash={ data.from.hash } alias={ data.from.name }/>
<CopyToClipboard text={ data.from.hash }/> <CopyToClipboard text={ data.from.hash }/>
</Address> </Address>
{ addressFromTags.length > 0 && (
<Flex columnGap={ 3 }>
{ addressFromTags }
</Flex>
) }
</DetailsInfoItem> </DetailsInfoItem>
<DetailsInfoItem <DetailsInfoItem
title={ data.to.is_contract ? 'Interacted with contract' : 'To' } title={ data.to.is_contract ? 'Interacted with contract' : 'To' }
...@@ -148,18 +166,25 @@ const TxDetails = () => { ...@@ -148,18 +166,25 @@ const TxDetails = () => {
<AddressLink ml={ 2 } hash={ data.to.hash } alias={ data.to.name }/> <AddressLink ml={ 2 } hash={ data.to.hash } alias={ data.to.name }/>
<CopyToClipboard text={ data.to.hash }/> <CopyToClipboard text={ data.to.hash }/>
</Address> </Address>
{ /* todo_tom Nikita should add to api later */ } { addressToTags.length > 0 && (
{ /* <Tag colorScheme="orange" variant="solid" flexShrink={ 0 }>SANA</Tag> */ } <Flex columnGap={ 3 }>
{ /* <Tooltip label="Contract execution completed"> { addressToTags }
<chakra.span display="inline-flex"> </Flex>
<Icon as={ successIcon } boxSize={ 4 } ml={ 2 } color="green.500" cursor="pointer"/> ) }
</chakra.span> { data.to.is_contract && data.result === 'success' && (
</Tooltip> */ } <Tooltip label="Contract execution completed">
{ /* <Tooltip label="Error occured during contract execution"> <chakra.span display="inline-flex">
<chakra.span display="inline-flex"> <Icon as={ successIcon } boxSize={ 4 } color="green.500" cursor="pointer"/>
<Icon as={ errorIcon } boxSize={ 4 } ml={ 2 } color="red.500" cursor="pointer"/> </chakra.span>
</chakra.span> </Tooltip>
</Tooltip> */ } ) }
{ data.to.is_contract && Boolean(data.status) && data.result !== 'success' && (
<Tooltip label="Error occured during contract execution">
<chakra.span display="inline-flex">
<Icon as={ errorIcon } boxSize={ 4 } color="red.500" cursor="pointer"/>
</chakra.span>
</Tooltip>
) }
{ /* <TokenSnippet symbol="UP" name="User Pay" hash="0xA17ed5dFc62D0a3E74D69a0503AE9FdA65d9f212" ml={ 3 }/> */ } { /* <TokenSnippet symbol="UP" name="User Pay" hash="0xA17ed5dFc62D0a3E74D69a0503AE9FdA65d9f212" ml={ 3 }/> */ }
</DetailsInfoItem> </DetailsInfoItem>
{ TOKEN_TRANSFERS.map(({ title, hint, type }) => { { TOKEN_TRANSFERS.map(({ title, hint, type }) => {
......
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