Commit ac0ac2b1 authored by tom's avatar tom

refactor AddressDetails

parent 1f8e6709
...@@ -10,14 +10,14 @@ import fetchApi from 'nextjs/utils/fetchApi'; ...@@ -10,14 +10,14 @@ import fetchApi from 'nextjs/utils/fetchApi';
import config from 'configs/app'; import config from 'configs/app';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
// import Address from 'ui/pages/Address'; import Address from 'ui/pages/Address';
const pathname: Route['pathname'] = '/address/[hash]'; const pathname: Route['pathname'] = '/address/[hash]';
const Page: NextPage<Props<typeof pathname>> = (props: Props<typeof pathname>) => { const Page: NextPage<Props<typeof pathname>> = (props: Props<typeof pathname>) => {
return ( return (
<PageNextJs pathname={ pathname } query={ props.query } apiData={ props.apiData }> <PageNextJs pathname={ pathname } query={ props.query } apiData={ props.apiData }>
{ /* <Address/> */ } <Address/>
</PageNextJs> </PageNextJs>
); );
}; };
......
...@@ -26,7 +26,7 @@ export const recipe = defineSlotRecipe({ ...@@ -26,7 +26,7 @@ export const recipe = defineSlotRecipe({
transition: 'translate 400ms, scale 400ms, opacity 200ms', transition: 'translate 400ms, scale 400ms, opacity 200ms',
transitionTimingFunction: 'cubic-bezier(0.06, 0.71, 0.55, 1)', transitionTimingFunction: 'cubic-bezier(0.06, 0.71, 0.55, 1)',
}, },
bg: 'alert.bg.neutral', bg: 'alert.bg.info',
color: 'alert.fg', color: 'alert.fg',
boxShadow: 'xl', boxShadow: 'xl',
'--toast-trigger-bg': 'colors.bg.muted', '--toast-trigger-bg': 'colors.bg.muted',
......
import { Box, Text, Grid } from '@chakra-ui/react'; import { Box, Text } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -94,11 +94,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -94,11 +94,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
return ( return (
<> <>
{ addressQuery.isDegradedData && <ServiceDegradationWarning isLoading={ addressQuery.isPlaceholderData } mb={ 6 }/> } { addressQuery.isDegradedData && <ServiceDegradationWarning isLoading={ addressQuery.isPlaceholderData } mb={ 6 }/> }
<Grid <DetailedInfo.Container templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} >
columnGap={ 8 }
rowGap={{ base: 1, lg: 3 }}
templateColumns={{ base: 'minmax(0, 1fr)', lg: 'auto minmax(0, 1fr)' }} overflow="hidden"
>
<AddressAlternativeFormat isLoading={ addressQuery.isPlaceholderData } addressHash={ addressHash }/> <AddressAlternativeFormat isLoading={ addressQuery.isPlaceholderData } addressHash={ addressHash }/>
{ data.filecoin?.id && ( { data.filecoin?.id && (
...@@ -318,7 +314,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => { ...@@ -318,7 +314,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
) } ) }
<DetailedInfoSponsoredItem isLoading={ addressQuery.isPlaceholderData }/> <DetailedInfoSponsoredItem isLoading={ addressQuery.isPlaceholderData }/>
</Grid> </DetailedInfo.Container>
</> </>
); );
}; };
......
...@@ -61,7 +61,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender = ...@@ -61,7 +61,7 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender =
const [ socketAlert, setSocketAlert ] = React.useState(''); const [ socketAlert, setSocketAlert ] = React.useState('');
const [ newItemsCount, setNewItemsCount ] = React.useState(0); const [ newItemsCount, setNewItemsCount ] = React.useState(0);
const [ sort, setSort ] = React.useState<TransactionsSortingValue | undefined>(getSortValueFromQuery<TransactionsSortingValue>(router.query, SORT_OPTIONS)); const [ sort, setSort ] = React.useState<TransactionsSortingValue>(getSortValueFromQuery<TransactionsSortingValue>(router.query, SORT_OPTIONS) || 'default');
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const currentAddress = getQueryParamString(router.query.hash); const currentAddress = getQueryParamString(router.query.hash);
...@@ -165,14 +165,15 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender = ...@@ -165,14 +165,15 @@ const AddressTxs = ({ scrollRef, overloadCount = OVERLOAD_COUNT, shouldRender =
return null; return null;
} }
const filter = ( // const filter = (
<AddressTxsFilter // <AddressTxsFilter
defaultFilter={ filterValue } // defaultFilter={ filterValue }
onFilterChange={ handleFilterChange } // onFilterChange={ handleFilterChange }
hasActiveFilter={ Boolean(filterValue) } // hasActiveFilter={ Boolean(filterValue) }
isLoading={ addressTxsQuery.pagination.isLoading } // isLoading={ addressTxsQuery.pagination.isLoading }
/> // />
); // );
const filter = null;
const csvExportLink = ( const csvExportLink = (
<AddressCsvExportLink <AddressCsvExportLink
......
...@@ -74,34 +74,34 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder ...@@ -74,34 +74,34 @@ export default function useContractTabs(data: Address | undefined, isPlaceholder
return React.useMemo(() => { return React.useMemo(() => {
return { return {
tabs: [ tabs: [
data?.hash && { // data?.hash && {
id: 'contract_code' as const, // id: 'contract_code' as const,
title: 'Code', // title: 'Code',
component: <ContractDetails mainContractQuery={ contractQuery } channel={ channel } addressHash={ data.hash }/>, // component: <ContractDetails mainContractQuery={ contractQuery } channel={ channel } addressHash={ data.hash }/>,
subTabs: CONTRACT_DETAILS_TAB_IDS as unknown as Array<string>, // subTabs: CONTRACT_DETAILS_TAB_IDS as unknown as Array<string>,
}, // },
contractQuery.data?.abi && { // contractQuery.data?.abi && {
id: [ 'read_write_contract' as const, 'read_contract' as const, 'write_contract' as const ], // id: [ 'read_write_contract' as const, 'read_contract' as const, 'write_contract' as const ],
title: 'Read/Write contract', // title: 'Read/Write contract',
component: <ContractMethodsRegular abi={ contractQuery.data.abi } isLoading={ contractQuery.isPlaceholderData }/>, // component: <ContractMethodsRegular abi={ contractQuery.data.abi } isLoading={ contractQuery.isPlaceholderData }/>,
}, // },
verifiedImplementations.length > 0 && { // verifiedImplementations.length > 0 && {
id: [ 'read_write_proxy' as const, 'read_proxy' as const, 'write_proxy' as const ], // id: [ 'read_write_proxy' as const, 'read_proxy' as const, 'write_proxy' as const ],
title: 'Read/Write proxy', // title: 'Read/Write proxy',
component: <ContractMethodsProxy implementations={ verifiedImplementations } isLoading={ contractQuery.isPlaceholderData }/>, // component: <ContractMethodsProxy implementations={ verifiedImplementations } isLoading={ contractQuery.isPlaceholderData }/>,
}, // },
config.features.account.isEnabled && { // config.features.account.isEnabled && {
id: [ 'read_write_custom_methods' as const, 'read_custom_methods' as const, 'write_custom_methods' as const ], // id: [ 'read_write_custom_methods' as const, 'read_custom_methods' as const, 'write_custom_methods' as const ],
title: 'Custom ABI', // title: 'Custom ABI',
component: <ContractMethodsCustom isLoading={ contractQuery.isPlaceholderData }/>, // component: <ContractMethodsCustom isLoading={ contractQuery.isPlaceholderData }/>,
}, // },
hasMudTab && { // hasMudTab && {
id: 'mud_system' as const, // id: 'mud_system' as const,
title: 'MUD System', // title: 'MUD System',
component: mudSystemsQuery.isPlaceholderData ? // component: mudSystemsQuery.isPlaceholderData ?
<ContentLoader/> : // <ContentLoader/> :
<ContractMethodsMudSystem items={ mudSystemsQuery.data?.items ?? [] }/>, // <ContractMethodsMudSystem items={ mudSystemsQuery.data?.items ?? [] }/>,
}, // },
].filter(Boolean), ].filter(Boolean),
isLoading: contractQuery.isPlaceholderData, isLoading: contractQuery.isPlaceholderData,
}; };
......
...@@ -7,8 +7,8 @@ import type { AddressCounters } from 'types/api/address'; ...@@ -7,8 +7,8 @@ import type { AddressCounters } from 'types/api/address';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import type { ResourceError } from 'lib/api/resources'; import type { ResourceError } from 'lib/api/resources';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Link } from 'toolkit/chakra/link';
import LinkInternal from 'ui/shared/links/LinkInternal'; import { Skeleton } from 'toolkit/chakra/skeleton';
interface Props { interface Props {
prop: keyof AddressCounters; prop: keyof AddressCounters;
...@@ -27,7 +27,7 @@ const PROP_TO_TAB = { ...@@ -27,7 +27,7 @@ const PROP_TO_TAB = {
const AddressCounterItem = ({ prop, query, address, onClick, isAddressQueryLoading, isDegradedData }: Props) => { const AddressCounterItem = ({ prop, query, address, onClick, isAddressQueryLoading, isDegradedData }: Props) => {
if (query.isPlaceholderData || isAddressQueryLoading) { if (query.isPlaceholderData || isAddressQueryLoading) {
return <Skeleton h={ 5 } w="80px" borderRadius="full"/>; return <Skeleton loading h={ 5 } w="80px" borderRadius="full"/>;
} }
const data = query.data?.[prop]; const data = query.data?.[prop];
...@@ -51,9 +51,9 @@ const AddressCounterItem = ({ prop, query, address, onClick, isAddressQueryLoadi ...@@ -51,9 +51,9 @@ const AddressCounterItem = ({ prop, query, address, onClick, isAddressQueryLoadi
} }
return ( return (
<LinkInternal href={ route({ pathname: '/address/[hash]', query: { hash: address, tab: PROP_TO_TAB[prop] } }) } onClick={ onClick }> <Link href={ route({ pathname: '/address/[hash]', query: { hash: address, tab: PROP_TO_TAB[prop] } }) } onClick={ onClick }>
{ Number(data).toLocaleString() } { Number(data).toLocaleString() }
</LinkInternal> </Link>
); );
} }
} }
......
...@@ -23,7 +23,7 @@ const AddressImplementations = ({ data, isLoading }: Props) => { ...@@ -23,7 +23,7 @@ const AddressImplementations = ({ data, isLoading }: Props) => {
> >
{ `Implementation${ hasManyItems ? 's' : '' }` } { `Implementation${ hasManyItems ? 's' : '' }` }
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailsInfoItem.ValueWithScroll <DetailedInfo.ItemValueWithScroll
gradientHeight={ 48 } gradientHeight={ 48 }
onScrollVisibilityChange={ setHasScroll } onScrollVisibilityChange={ setHasScroll }
rowGap={ 2 } rowGap={ 2 }
...@@ -42,7 +42,7 @@ const AddressImplementations = ({ data, isLoading }: Props) => { ...@@ -42,7 +42,7 @@ const AddressImplementations = ({ data, isLoading }: Props) => {
noIcon noIcon
/> />
)) } )) }
</DetailsInfoItem.ValueWithScroll> </DetailedInfo.ItemValueWithScroll>
</> </>
); );
}; };
......
import { Alert, Flex, chakra } from '@chakra-ui/react'; import { Flex, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { AddressMetadataTagFormatted } from 'types/client/addressMetadata'; import type { AddressMetadataTagFormatted } from 'types/client/addressMetadata';
import { Alert } from 'toolkit/chakra/alert';
interface Props { interface Props {
tags: Array<AddressMetadataTagFormatted> | undefined; tags: Array<AddressMetadataTagFormatted> | undefined;
className?: string; className?: string;
...@@ -25,11 +27,11 @@ const AddressMetadataAlert = ({ tags, className }: Props) => { ...@@ -25,11 +27,11 @@ const AddressMetadataAlert = ({ tags, className }: Props) => {
color={ noteTag.meta?.alertTextColor } color={ noteTag.meta?.alertTextColor }
whiteSpace="pre-wrap" whiteSpace="pre-wrap"
display="inline-block" display="inline-block"
sx={{ css={{
'& a': { '& a': {
color: 'link', color: 'link',
_hover: { _hover: {
color: 'link_hovered', color: 'link.primary.hover',
}, },
}, },
}} }}
......
import { Image, Tooltip } from '@chakra-ui/react';
import { capitalize } from 'es-toolkit'; import { capitalize } from 'es-toolkit';
import React from 'react'; import React from 'react';
...@@ -6,8 +5,9 @@ import type { MultichainProviderConfigParsed } from 'types/client/multichainProv ...@@ -6,8 +5,9 @@ import type { MultichainProviderConfigParsed } from 'types/client/multichainProv
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import LinkExternal from 'ui/shared/links/LinkExternal'; import { Image } from 'toolkit/chakra/image';
import LinkInternal from 'ui/shared/links/LinkInternal'; import { Link } from 'toolkit/chakra/link';
import { Tooltip } from 'toolkit/chakra/tooltip';
const TEMPLATE_ADDRESS = '{address}'; const TEMPLATE_ADDRESS = '{address}';
...@@ -28,39 +28,28 @@ const AddressMultichainButton = ({ item, addressHash, onClick, hasSingleProvider ...@@ -28,39 +28,28 @@ const AddressMultichainButton = ({ item, addressHash, onClick, hasSingleProvider
{ capitalize(item.name) } { capitalize(item.name) }
</> </>
) : ( ) : (
<Tooltip label={ capitalize(item.name) }>{ buttonIcon }</Tooltip> <Tooltip content={ capitalize(item.name) }>{ buttonIcon }</Tooltip>
); );
const linkProps = {
variant: hasSingleProvider ? 'subtle' as const : undefined,
display: 'flex',
alignItems: 'center',
fontSize: 'sm',
lineHeight: 5,
fontWeight: 500,
onClick,
};
try { try {
const portfolioUrlString = item.urlTemplate.replace(TEMPLATE_ADDRESS, addressHash); const portfolioUrlString = item.urlTemplate.replace(TEMPLATE_ADDRESS, addressHash);
const portfolioUrl = new URL(portfolioUrlString); const portfolioUrl = new URL(portfolioUrlString);
portfolioUrl.searchParams.append('utm_source', 'blockscout'); portfolioUrl.searchParams.append('utm_source', 'blockscout');
portfolioUrl.searchParams.append('utm_medium', 'address'); portfolioUrl.searchParams.append('utm_medium', 'address');
const dappId = item.dappId; const dappId = item.dappId;
return typeof dappId === 'string' ? ( const isExternal = typeof dappId !== 'string';
<LinkInternal
href={ route({ pathname: '/apps/[id]', query: { id: dappId, url: portfolioUrl.toString() } }) } return (
{ ...linkProps } <Link
> external={ isExternal }
{ buttonContent } href={ isExternal ? portfolioUrl.toString() : route({ pathname: '/apps/[id]', query: { id: dappId, url: portfolioUrl.toString() } }) }
</LinkInternal> variant={ hasSingleProvider ? 'underlaid' : undefined }
) : ( textStyle="sm"
<LinkExternal fontWeight="medium"
href={ portfolioUrl.toString() } onClick={ onClick }
{ ...linkProps }
> >
{ buttonContent } { buttonContent }
</LinkExternal> </Link>
); );
} catch (error) {} } catch (error) {}
......
...@@ -2,7 +2,7 @@ import React from 'react'; ...@@ -2,7 +2,7 @@ import React from 'react';
import type { Address } from 'types/api/address'; import type { Address } from 'types/api/address';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo'; import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
...@@ -43,7 +43,7 @@ const AddressNameInfo = ({ data, isLoading }: Props) => { ...@@ -43,7 +43,7 @@ const AddressNameInfo = ({ data, isLoading }: Props) => {
Contract name Contract name
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !isLoading }> <Skeleton loading={ isLoading }>
{ data.name } { data.name }
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
...@@ -61,7 +61,7 @@ const AddressNameInfo = ({ data, isLoading }: Props) => { ...@@ -61,7 +61,7 @@ const AddressNameInfo = ({ data, isLoading }: Props) => {
Validator name Validator name
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !isLoading }> <Skeleton loading={ isLoading }>
{ data.name } { data.name }
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
......
...@@ -6,7 +6,7 @@ import type { Address } from 'types/api/address'; ...@@ -6,7 +6,7 @@ import type { Address } from 'types/api/address';
import config from 'configs/app'; import config from 'configs/app';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
import { getTokensTotalInfo } from '../utils/tokenUtils'; import { getTokensTotalInfo } from '../utils/tokenUtils';
...@@ -68,7 +68,7 @@ const AddressNetWorth = ({ addressData, isLoading, addressHash }: Props) => { ...@@ -68,7 +68,7 @@ const AddressNetWorth = ({ addressData, isLoading, addressHash }: Props) => {
} }
return ( return (
<Skeleton display="flex" alignItems="center" flexWrap="wrap" isLoaded={ !isLoading && !(addressData?.has_tokens && isPending) } gap={ 2 }> <Skeleton display="flex" alignItems="center" flexWrap="wrap" loading={ isLoading && !(addressData?.has_tokens && isPending) } gap={ 2 }>
<Text> <Text>
{ (isError || !addressData?.exchange_rate) ? 'N/A' : `${ prefix }$${ totalUsd.toFormat(2) }` } { (isError || !addressData?.exchange_rate) ? 'N/A' : `${ prefix }$${ totalUsd.toFormat(2) }` }
</Text> </Text>
......
import { Image } from '@chakra-ui/react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
import * as v from 'valibot'; import * as v from 'valibot';
import config from 'configs/app'; import config from 'configs/app';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Image } from 'toolkit/chakra/image';
import LinkExternal from 'ui/shared/links/LinkExternal'; import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
const feature = config.features.saveOnGas; const feature = config.features.saveOnGas;
...@@ -76,11 +76,11 @@ const AddressSaveOnGas = ({ gasUsed, address }: Props) => { ...@@ -76,11 +76,11 @@ const AddressSaveOnGas = ({ gasUsed, address }: Props) => {
return ( return (
<> <>
<TextSeparator color="border.divider"/> <TextSeparator color="border.divider"/>
<Skeleton isLoaded={ !query.isPlaceholderData } display="flex" alignItems="center" columnGap={ 2 }> <Skeleton loading={ query.isPlaceholderData } display="flex" alignItems="center" columnGap={ 2 }>
<Image src="/static/gas_hawk_logo.svg" w="15px" h="20px" alt="GasHawk logo"/> <Image src="/static/gas_hawk_logo.svg" w="15px" h="20px" alt="GasHawk logo"/>
<LinkExternal href="https://www.gashawk.io?utm_source=blockscout&utm_medium=address" fontSize="sm"> <Link href="https://www.gashawk.io?utm_source=blockscout&utm_medium=address" fontSize="sm" external>
Save { percent.toLocaleString(undefined, { maximumFractionDigits: 0 }) }% with GasHawk Save { percent.toLocaleString(undefined, { maximumFractionDigits: 0 }) }% with GasHawk
</LinkExternal> </Link>
</Skeleton> </Skeleton>
</> </>
); );
......
import { Tag } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FilecoinActorType } from 'types/api/addressParams'; import type { FilecoinActorType } from 'types/api/addressParams';
import { Badge } from 'toolkit/chakra/badge';
const ACTOR_TYPES: Record<FilecoinActorType, string> = { const ACTOR_TYPES: Record<FilecoinActorType, string> = {
account: 'Account', account: 'Account',
cron: 'Scheduled Tasks', cron: 'Scheduled Tasks',
...@@ -33,7 +34,7 @@ const FilecoinActorTag = ({ actorType }: Props) => { ...@@ -33,7 +34,7 @@ const FilecoinActorTag = ({ actorType }: Props) => {
return null; return null;
} }
return <Tag colorScheme="gray">{ text }</Tag>; return <Badge colorPalette="gray">{ text }</Badge>;
}; };
export default FilecoinActorTag; export default FilecoinActorTag;
import { Box, Flex, IconButton, Tooltip } from '@chakra-ui/react'; import { Box, Flex } from '@chakra-ui/react';
import { useQueryClient, useIsFetching } from '@tanstack/react-query'; import { useQueryClient, useIsFetching } from '@tanstack/react-query';
import { sumBy } from 'es-toolkit'; import { sumBy } from 'es-toolkit';
import NextLink from 'next/link'; import NextLink from 'next/link';
...@@ -11,7 +11,9 @@ import { getResourceKey } from 'lib/api/useApiQuery'; ...@@ -11,7 +11,9 @@ import { getResourceKey } from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import getQueryParamString from 'lib/router/getQueryParamString'; import getQueryParamString from 'lib/router/getQueryParamString';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { IconButton } from 'toolkit/chakra/icon-button';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { Tooltip } from 'toolkit/chakra/tooltip';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import useFetchTokens from '../utils/useFetchTokens'; import useFetchTokens from '../utils/useFetchTokens';
...@@ -44,8 +46,8 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -44,8 +46,8 @@ const TokenSelect = ({ onClick }: Props) => {
if (isPending) { if (isPending) {
return ( return (
<Flex columnGap={ 3 }> <Flex columnGap={ 3 }>
<Skeleton h={ 8 } w="150px" borderRadius="base"/> <Skeleton loading h={ 8 } w="150px" borderRadius="base"/>
<Skeleton h={ 8 } w={ 9 } borderRadius="base"/> <Skeleton loading h={ 8 } w={ 9 } borderRadius="base"/>
</Flex> </Flex>
); );
} }
...@@ -61,8 +63,9 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -61,8 +63,9 @@ const TokenSelect = ({ onClick }: Props) => {
<TokenSelectMobile data={ data } isLoading={ tokensIsFetching === 1 }/> : <TokenSelectMobile data={ data } isLoading={ tokensIsFetching === 1 }/> :
<TokenSelectDesktop data={ data } isLoading={ tokensIsFetching === 1 }/> <TokenSelectDesktop data={ data } isLoading={ tokensIsFetching === 1 }/>
} }
<Tooltip label="Show all tokens"> <Tooltip content="Show all tokens">
<Box> <Box>
{ /* TODO @tom2drum: replace with Link */ }
<NextLink href={{ pathname: '/address/[hash]', query: { hash: addressHash, tab: 'tokens' } }} passHref legacyBehavior> <NextLink href={{ pathname: '/address/[hash]', query: { hash: addressHash, tab: 'tokens' } }} passHref legacyBehavior>
<IconButton <IconButton
aria-label="Show all tokens" aria-label="Show all tokens"
...@@ -70,10 +73,11 @@ const TokenSelect = ({ onClick }: Props) => { ...@@ -70,10 +73,11 @@ const TokenSelect = ({ onClick }: Props) => {
size="sm" size="sm"
pl="6px" pl="6px"
pr="6px" pr="6px"
icon={ <IconSvg name="wallet" boxSize={ 5 }/> }
as="a" as="a"
onClick={ handleIconButtonClick } onClick={ handleIconButtonClick }
/> >
<IconSvg name="wallet" boxSize={ 5 }/>
</IconButton>
</NextLink> </NextLink>
</Box> </Box>
</Tooltip> </Tooltip>
......
import { Box, Button, chakra, useColorModeValue } from '@chakra-ui/react'; import { Box, chakra } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FormattedData } from './types'; import type { FormattedData } from './types';
import { space } from 'lib/html-entities'; import { space } from 'lib/html-entities';
import * as mixpanel from 'lib/mixpanel/index'; import * as mixpanel from 'lib/mixpanel/index';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Button } from 'toolkit/chakra/button';
import { Skeleton } from 'toolkit/chakra/skeleton';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import { getTokensTotalInfo } from '../utils/tokenUtils'; import { getTokensTotalInfo } from '../utils/tokenUtils';
...@@ -13,13 +14,11 @@ import { getTokensTotalInfo } from '../utils/tokenUtils'; ...@@ -13,13 +14,11 @@ import { getTokensTotalInfo } from '../utils/tokenUtils';
interface Props { interface Props {
isOpen: boolean; isOpen: boolean;
isLoading: boolean; isLoading: boolean;
onClick: () => void;
data: FormattedData; data: FormattedData;
} }
const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: React.ForwardedRef<HTMLButtonElement>) => { const TokenSelectButton = ({ isOpen, isLoading, data, ...rest }: Props, ref: React.ForwardedRef<HTMLButtonElement>) => {
const { usd, num, isOverflow } = getTokensTotalInfo(data); const { usd, num, isOverflow } = getTokensTotalInfo(data);
const skeletonBgColor = useColorModeValue('white', 'black');
const prefix = isOverflow ? '>' : ''; const prefix = isOverflow ? '>' : '';
...@@ -29,27 +28,27 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea ...@@ -29,27 +28,27 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea
} }
mixpanel.logEvent(mixpanel.EventTypes.PAGE_WIDGET, { Type: 'Tokens dropdown' }); mixpanel.logEvent(mixpanel.EventTypes.PAGE_WIDGET, { Type: 'Tokens dropdown' });
onClick(); }, [ isLoading, isOpen ]);
}, [ isLoading, isOpen, onClick ]);
return ( return (
<Box position="relative"> <Box position="relative" className="group">
<Button <Button
ref={ ref } ref={ ref }
size="sm" size="sm"
variant="outline" variant="dropdown"
colorScheme="gray"
onClick={ handleClick } onClick={ handleClick }
isActive={ isOpen } gap={ 0 }
aria-label="Token select" aria-label="Token select"
{ ...rest }
> >
<IconSvg name="tokens" boxSize={ 4 } mr={ 2 }/> <IconSvg name="tokens" boxSize={ 4 } mr={ 2 }/>
<chakra.span fontWeight={ 600 }>{ prefix }{ num }</chakra.span> <chakra.span fontWeight={ 600 }>{ prefix }{ num }</chakra.span>
<chakra.span <chakra.span
whiteSpace="pre" whiteSpace="pre"
color="text_secondary" color={ isOpen ? 'inherit' : 'text.secondary' }
fontWeight={ 400 } fontWeight={ 400 }
maxW={{ base: 'calc(100vw - 230px)', lg: '500px' }} maxW={{ base: 'calc(100vw - 230px)', lg: '500px' }}
_groupHover={{ color: 'inherit' }}
overflow="hidden" overflow="hidden"
textOverflow="ellipsis" textOverflow="ellipsis"
> >
...@@ -57,7 +56,18 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea ...@@ -57,7 +56,18 @@ const TokenSelectButton = ({ isOpen, isLoading, onClick, data }: Props, ref: Rea
</chakra.span> </chakra.span>
<IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/> <IconSvg name="arrows/east-mini" transform={ isOpen ? 'rotate(90deg)' : 'rotate(-90deg)' } transitionDuration="faster" boxSize={ 5 } ml={ 3 }/>
</Button> </Button>
{ isLoading && !isOpen && <Skeleton h="100%" w="100%" position="absolute" top={ 0 } left={ 0 } bgColor={ skeletonBgColor } borderRadius="base"/> } { isLoading && !isOpen && (
<Skeleton
loading
h="100%"
w="100%"
position="absolute"
top={ 0 }
left={ 0 }
bgColor={{ _light: 'white', _dark: 'black' }}
borderRadius="base"
/>
) }
</Box> </Box>
); );
}; };
......
import { PopoverTrigger, PopoverContent, PopoverBody, useDisclosure } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FormattedData } from './types'; import type { FormattedData } from './types';
import Popover from 'ui/shared/chakra/Popover'; import { PopoverRoot, PopoverTrigger, PopoverContent, PopoverBody } from 'toolkit/chakra/popover';
import { useDisclosure } from 'toolkit/hooks/useDisclosure';
import TokenSelectButton from './TokenSelectButton'; import TokenSelectButton from './TokenSelectButton';
import TokenSelectMenu from './TokenSelectMenu'; import TokenSelectMenu from './TokenSelectMenu';
...@@ -15,21 +15,21 @@ interface Props { ...@@ -15,21 +15,21 @@ interface Props {
} }
const TokenSelectDesktop = ({ data, isLoading }: Props) => { const TokenSelectDesktop = ({ data, isLoading }: Props) => {
const { isOpen, onToggle, onClose } = useDisclosure(); const { open, onOpenChange } = useDisclosure();
const result = useTokenSelect(data); const result = useTokenSelect(data);
return ( return (
<Popover isOpen={ isOpen } onClose={ onClose } placement="bottom-start" isLazy> <PopoverRoot open={ open } onOpenChange={ onOpenChange }>
<PopoverTrigger> <PopoverTrigger>
<TokenSelectButton isOpen={ isOpen } onClick={ onToggle } data={ result.data } isLoading={ isLoading }/> <TokenSelectButton data={ result.data } isLoading={ isLoading } isOpen={ open }/>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent w="355px" maxH="450px" overflowY="scroll"> <PopoverContent w="355px" maxH="450px" overflowY="scroll">
<PopoverBody px={ 4 } py={ 6 } boxShadow="2xl" > <PopoverBody>
<TokenSelectMenu { ...result }/> <TokenSelectMenu { ...result }/>
</PopoverBody> </PopoverBody>
</PopoverContent> </PopoverContent>
</Popover> </PopoverRoot>
); );
}; };
......
import { chakra, Flex, useColorModeValue } from '@chakra-ui/react'; import { chakra, Flex } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import { Link } from 'toolkit/chakra/link';
import TokenEntity from 'ui/shared/entities/token/TokenEntity'; import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import LinkInternal from 'ui/shared/links/LinkInternal';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
import type { TokenEnhancedData } from '../utils/tokenUtils'; import type { TokenEnhancedData } from '../utils/tokenUtils';
...@@ -71,7 +71,7 @@ const TokenSelectItem = ({ data }: Props) => { ...@@ -71,7 +71,7 @@ const TokenSelectItem = ({ data }: Props) => {
const url = route({ pathname: '/token/[hash]', query: { hash: data.token.address } }); const url = route({ pathname: '/token/[hash]', query: { hash: data.token.address } });
return ( return (
<LinkInternal <Link
px={ 1 } px={ 1 }
py="10px" py="10px"
display="flex" display="flex"
...@@ -80,7 +80,7 @@ const TokenSelectItem = ({ data }: Props) => { ...@@ -80,7 +80,7 @@ const TokenSelectItem = ({ data }: Props) => {
borderColor="border.divider" borderColor="border.divider"
borderBottomWidth="1px" borderBottomWidth="1px"
_hover={{ _hover={{
bgColor: useColorModeValue('blue.50', 'gray.800'), bgColor: { _light: 'blue.50', _dark: 'gray.800' },
}} }}
color="unset" color="unset"
fontSize="sm" fontSize="sm"
...@@ -102,7 +102,7 @@ const TokenSelectItem = ({ data }: Props) => { ...@@ -102,7 +102,7 @@ const TokenSelectItem = ({ data }: Props) => {
<Flex alignItems="center" justifyContent="space-between" w="100%" whiteSpace="nowrap"> <Flex alignItems="center" justifyContent="space-between" w="100%" whiteSpace="nowrap">
{ secondRow } { secondRow }
</Flex> </Flex>
</LinkInternal> </Link>
); );
}; };
......
import { Text, Box, Input, InputGroup, InputLeftElement, useColorModeValue, Flex, Link } from '@chakra-ui/react'; import { Text, Box, Input, Flex } from '@chakra-ui/react';
import { sumBy } from 'es-toolkit'; import { sumBy } from 'es-toolkit';
import type { ChangeEvent } from 'react'; import type { ChangeEvent } from 'react';
import React from 'react'; import React from 'react';
...@@ -7,6 +7,8 @@ import type { FormattedData } from './types'; ...@@ -7,6 +7,8 @@ import type { FormattedData } from './types';
import type { TokenType } from 'types/api/token'; import type { TokenType } from 'types/api/token';
import { getTokenTypeName } from 'lib/token/tokenTypes'; import { getTokenTypeName } from 'lib/token/tokenTypes';
import { InputGroup } from 'toolkit/chakra/input-group';
import { Link } from 'toolkit/chakra/link';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import type { Sort } from '../utils/tokenUtils'; import type { Sort } from '../utils/tokenUtils';
...@@ -24,23 +26,16 @@ interface Props { ...@@ -24,23 +26,16 @@ interface Props {
} }
const TokenSelectMenu = ({ erc20sort, erc1155sort, erc404sort, filteredData, onInputChange, onSortClick, searchTerm }: Props) => { const TokenSelectMenu = ({ erc20sort, erc1155sort, erc404sort, filteredData, onInputChange, onSortClick, searchTerm }: Props) => {
const searchIconColor = useColorModeValue('blackAlpha.600', 'whiteAlpha.600');
const hasFilteredResult = sumBy(Object.values(filteredData), ({ items }) => items.length) > 0; const hasFilteredResult = sumBy(Object.values(filteredData), ({ items }) => items.length) > 0;
return ( return (
<> <>
<InputGroup size="xs" mb={ 5 }> <InputGroup
<InputLeftElement > startElement={ <IconSvg name="search" boxSize={ 4 } color={{ _light: 'blackAlpha.600', _dark: 'whiteAlpha.600' }}/> }
<IconSvg name="search" boxSize={ 4 } color={ searchIconColor }/> startOffset="38px"
</InputLeftElement> mb={ 5 }
<Input >
paddingInlineStart="38px" <Input placeholder="Search by token name" onChange={ onInputChange } size="sm" bgColor="dialog.bg"/>
placeholder="Search by token name"
ml="1px"
onChange={ onInputChange }
bgColor="dialog.bg"
/>
</InputGroup> </InputGroup>
<Flex flexDir="column" rowGap={ 6 }> <Flex flexDir="column" rowGap={ 6 }>
{ Object.entries(filteredData).sort(sortTokenGroups).map(([ tokenType, tokenInfo ]) => { { Object.entries(filteredData).sort(sortTokenGroups).map(([ tokenType, tokenInfo ]) => {
......
import { useDisclosure, Modal, ModalContent, ModalCloseButton } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { FormattedData } from './types'; import type { FormattedData } from './types';
import { DialogContent, DialogRoot } from 'toolkit/chakra/dialog';
import { useDisclosure } from 'toolkit/hooks/useDisclosure';
import TokenSelectButton from './TokenSelectButton'; import TokenSelectButton from './TokenSelectButton';
import TokenSelectMenu from './TokenSelectMenu'; import TokenSelectMenu from './TokenSelectMenu';
import useTokenSelect from './useTokenSelect'; import useTokenSelect from './useTokenSelect';
...@@ -13,18 +15,17 @@ interface Props { ...@@ -13,18 +15,17 @@ interface Props {
} }
const TokenSelectMobile = ({ data, isLoading }: Props) => { const TokenSelectMobile = ({ data, isLoading }: Props) => {
const { isOpen, onToggle, onClose } = useDisclosure(); const { open, onOpenChange } = useDisclosure();
const result = useTokenSelect(data); const result = useTokenSelect(data);
return ( return (
<> <>
<TokenSelectButton isOpen={ isOpen } onClick={ onToggle } data={ result.data } isLoading={ isLoading }/> <TokenSelectButton isOpen={ open } data={ result.data } isLoading={ isLoading }/>
<Modal isOpen={ isOpen } onClose={ onClose } size="full"> <DialogRoot open={ open } onOpenChange={ onOpenChange } size="full">
<ModalContent> <DialogContent>
<ModalCloseButton/>
<TokenSelectMenu { ...result }/> <TokenSelectMenu { ...result }/>
</ModalContent> </DialogContent>
</Modal> </DialogRoot>
</> </>
); );
}; };
......
import { Box, Flex, HStack, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, HStack } from '@chakra-ui/react';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import React from 'react'; import React from 'react';
...@@ -19,6 +19,7 @@ import useSocketMessage from 'lib/socket/useSocketMessage'; ...@@ -19,6 +19,7 @@ import useSocketMessage from 'lib/socket/useSocketMessage';
import useFetchXStarScore from 'lib/xStarScore/useFetchXStarScore'; import useFetchXStarScore from 'lib/xStarScore/useFetchXStarScore';
import { ADDRESS_TABS_COUNTERS } from 'stubs/address'; import { ADDRESS_TABS_COUNTERS } from 'stubs/address';
import { USER_OPS_ACCOUNT } from 'stubs/userOps'; import { USER_OPS_ACCOUNT } from 'stubs/userOps';
import RoutedTabs from 'toolkit/components/RoutedTabs/RoutedTabs';
import AddressAccountHistory from 'ui/address/AddressAccountHistory'; import AddressAccountHistory from 'ui/address/AddressAccountHistory';
import AddressBlocksValidated from 'ui/address/AddressBlocksValidated'; import AddressBlocksValidated from 'ui/address/AddressBlocksValidated';
import AddressCoinBalance from 'ui/address/AddressCoinBalance'; import AddressCoinBalance from 'ui/address/AddressCoinBalance';
...@@ -54,7 +55,6 @@ import sortEntityTags from 'ui/shared/EntityTags/sortEntityTags'; ...@@ -54,7 +55,6 @@ import sortEntityTags from 'ui/shared/EntityTags/sortEntityTags';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import NetworkExplorers from 'ui/shared/NetworkExplorers'; import NetworkExplorers from 'ui/shared/NetworkExplorers';
import PageTitle from 'ui/shared/Page/PageTitle'; import PageTitle from 'ui/shared/Page/PageTitle';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
const TOKEN_TABS = [ 'tokens_erc20', 'tokens_nfts', 'tokens_nfts_collection', 'tokens_nfts_list' ]; const TOKEN_TABS = [ 'tokens_erc20', 'tokens_nfts', 'tokens_nfts_collection', 'tokens_nfts_list' ];
const PREDEFINED_TAG_PRIORITY = 100; const PREDEFINED_TAG_PRIORITY = 100;
...@@ -142,7 +142,6 @@ const AddressPageContent = () => { ...@@ -142,7 +142,6 @@ const AddressPageContent = () => {
}); });
const isSafeAddress = useIsSafeAddress(!addressQuery.isPlaceholderData && addressQuery.data?.is_contract ? hash : undefined); const isSafeAddress = useIsSafeAddress(!addressQuery.isPlaceholderData && addressQuery.data?.is_contract ? hash : undefined);
const safeIconColor = useColorModeValue('black', 'white');
const xStarQuery = useFetchXStarScore({ hash }); const xStarQuery = useFetchXStarScore({ hash });
...@@ -154,111 +153,111 @@ const AddressPageContent = () => { ...@@ -154,111 +153,111 @@ const AddressPageContent = () => {
const tabs: Array<RoutedTab> = React.useMemo(() => { const tabs: Array<RoutedTab> = React.useMemo(() => {
return [ return [
config.features.mudFramework.isEnabled && mudTablesCountQuery.data && mudTablesCountQuery.data > 0 && { // config.features.mudFramework.isEnabled && mudTablesCountQuery.data && mudTablesCountQuery.data > 0 && {
id: 'mud', // id: 'mud',
title: 'MUD', // title: 'MUD',
count: mudTablesCountQuery.data, // count: mudTablesCountQuery.data,
component: <AddressMud scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressMud scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
}, // },
{ {
id: 'txs', id: 'txs',
title: 'Transactions', title: 'Transactions',
count: addressTabsCountersQuery.data?.transactions_count, count: addressTabsCountersQuery.data?.transactions_count,
component: <AddressTxs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, component: <AddressTxs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
}, },
txInterpretation.isEnabled && txInterpretation.provider === 'noves' ? // txInterpretation.isEnabled && txInterpretation.provider === 'noves' ?
{ // {
id: 'account_history', // id: 'account_history',
title: 'Account history', // title: 'Account history',
component: <AddressAccountHistory scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressAccountHistory scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : // } :
undefined, // undefined,
config.features.userOps.isEnabled && Boolean(userOpsAccountQuery.data?.total_ops) ? // config.features.userOps.isEnabled && Boolean(userOpsAccountQuery.data?.total_ops) ?
{ // {
id: 'user_ops', // id: 'user_ops',
title: 'User operations', // title: 'User operations',
count: userOpsAccountQuery.data?.total_ops, // count: userOpsAccountQuery.data?.total_ops,
component: <AddressUserOps shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressUserOps shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : // } :
undefined, // undefined,
config.features.beaconChain.isEnabled && addressTabsCountersQuery.data?.withdrawals_count ? // config.features.beaconChain.isEnabled && addressTabsCountersQuery.data?.withdrawals_count ?
{ // {
id: 'withdrawals', // id: 'withdrawals',
title: 'Withdrawals', // title: 'Withdrawals',
count: addressTabsCountersQuery.data?.withdrawals_count, // count: addressTabsCountersQuery.data?.withdrawals_count,
component: <AddressWithdrawals scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressWithdrawals scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : // } :
undefined, // undefined,
{ // {
id: 'token_transfers', // id: 'token_transfers',
title: 'Token transfers', // title: 'Token transfers',
count: addressTabsCountersQuery.data?.token_transfers_count, // count: addressTabsCountersQuery.data?.token_transfers_count,
component: <AddressTokenTransfers scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressTokenTransfers scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
}, // },
{ // {
id: 'tokens', // id: 'tokens',
title: 'Tokens', // title: 'Tokens',
count: addressTabsCountersQuery.data?.token_balances_count, // count: addressTabsCountersQuery.data?.token_balances_count,
component: <AddressTokens shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressTokens shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
subTabs: TOKEN_TABS, // subTabs: TOKEN_TABS,
}, // },
{ // {
id: 'internal_txns', // id: 'internal_txns',
title: 'Internal txns', // title: 'Internal txns',
count: addressTabsCountersQuery.data?.internal_transactions_count, // count: addressTabsCountersQuery.data?.internal_transactions_count,
component: <AddressInternalTxs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressInternalTxs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
}, // },
addressTabsCountersQuery.data?.celo_election_rewards_count ? { // addressTabsCountersQuery.data?.celo_election_rewards_count ? {
id: 'epoch_rewards', // id: 'epoch_rewards',
title: 'Epoch rewards', // title: 'Epoch rewards',
count: addressTabsCountersQuery.data?.celo_election_rewards_count, // count: addressTabsCountersQuery.data?.celo_election_rewards_count,
component: <AddressEpochRewards scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressEpochRewards scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : undefined, // } : undefined,
{ // {
id: 'coin_balance_history', // id: 'coin_balance_history',
title: 'Coin balance history', // title: 'Coin balance history',
component: <AddressCoinBalance shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressCoinBalance shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
}, // },
addressTabsCountersQuery.data?.validations_count ? // addressTabsCountersQuery.data?.validations_count ?
{ // {
id: 'blocks_validated', // id: 'blocks_validated',
title: `Blocks ${ getNetworkValidationActionText() }`, // title: `Blocks ${ getNetworkValidationActionText() }`,
count: addressTabsCountersQuery.data?.validations_count, // count: addressTabsCountersQuery.data?.validations_count,
component: <AddressBlocksValidated scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressBlocksValidated scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : // } :
undefined, // undefined,
addressTabsCountersQuery.data?.logs_count ? // addressTabsCountersQuery.data?.logs_count ?
{ // {
id: 'logs', // id: 'logs',
title: 'Logs', // title: 'Logs',
count: addressTabsCountersQuery.data?.logs_count, // count: addressTabsCountersQuery.data?.logs_count,
component: <AddressLogs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>, // component: <AddressLogs scrollRef={ tabsScrollRef } shouldRender={ !isTabsLoading } isQueryEnabled={ areQueriesEnabled }/>,
} : // } :
undefined, // undefined,
addressQuery.data?.is_contract ? { // addressQuery.data?.is_contract ? {
id: 'contract', // id: 'contract',
title: () => { // title: () => {
if (addressQuery.data.is_verified) { // if (addressQuery.data.is_verified) {
return ( // return (
<> // <>
<span>Contract</span> // <span>Contract</span>
<IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/> // <IconSvg name="status/success" boxSize="14px" color="green.500" ml={ 1 }/>
</> // </>
); // );
} // }
return 'Contract'; // return 'Contract';
}, // },
component: ( // component: (
<AddressContract // <AddressContract
tabs={ contractTabs.tabs } // tabs={ contractTabs.tabs }
shouldRender={ !isTabsLoading } // shouldRender={ !isTabsLoading }
isLoading={ contractTabs.isLoading } // isLoading={ contractTabs.isLoading }
/> // />
), // ),
subTabs: CONTRACT_TAB_IDS, // subTabs: CONTRACT_TAB_IDS,
} : undefined, // } : undefined,
].filter(Boolean); ].filter(Boolean);
}, [ }, [
addressQuery.data, addressQuery.data,
...@@ -343,7 +342,7 @@ const AddressPageContent = () => { ...@@ -343,7 +342,7 @@ const AddressPageContent = () => {
const content = (addressQuery.isError || addressQuery.isDegradedData) ? const content = (addressQuery.isError || addressQuery.isDegradedData) ?
null : null :
<RoutedTabs tabs={ tabs } tabListProps={{ mt: 6 }} isLoading={ isTabsLoading }/>; <RoutedTabs tabs={ tabs } listProps={{ mt: 6 }} isLoading={ isTabsLoading }/>;
const backLink = React.useMemo(() => { const backLink = React.useMemo(() => {
if (appProps.referrer && appProps.referrer.includes('/accounts')) { if (appProps.referrer && appProps.referrer.includes('/accounts')) {
...@@ -367,51 +366,51 @@ const AddressPageContent = () => { ...@@ -367,51 +366,51 @@ const AddressPageContent = () => {
// In this case it returns 404 with empty payload, so we calculate check-summed hash on the client // In this case it returns 404 with empty payload, so we calculate check-summed hash on the client
const checkSummedHash = React.useMemo(() => addressQuery.data?.hash ?? getCheckedSummedAddress(hash), [ hash, addressQuery.data?.hash ]); const checkSummedHash = React.useMemo(() => addressQuery.data?.hash ?? getCheckedSummedAddress(hash), [ hash, addressQuery.data?.hash ]);
const titleSecondRow = ( // const titleSecondRow = (
<Flex alignItems="center" w="100%" columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}> // <Flex alignItems="center" w="100%" columnGap={ 2 } rowGap={ 2 } flexWrap={{ base: 'wrap', lg: 'nowrap' }}>
{ addressQuery.data?.ens_domain_name && ( // { addressQuery.data?.ens_domain_name && (
<EnsEntity // <EnsEntity
domain={ addressQuery.data?.ens_domain_name } // domain={ addressQuery.data?.ens_domain_name }
protocol={ !addressEnsDomainsQuery.isPending ? addressMainDomain?.protocol : null } // protocol={ !addressEnsDomainsQuery.isPending ? addressMainDomain?.protocol : null }
fontFamily="heading" // fontFamily="heading"
fontSize="lg" // fontSize="lg"
fontWeight={ 500 } // fontWeight={ 500 }
mr={ 1 } // mr={ 1 }
maxW="300px" // maxW="300px"
/> // />
) } // ) }
<AddressEntity // <AddressEntity
address={{ // address={{
...addressQuery.data, // ...addressQuery.data,
hash: checkSummedHash, // hash: checkSummedHash,
name: '', // name: '',
ens_domain_name: '', // ens_domain_name: '',
implementations: null, // implementations: null,
}} // }}
isLoading={ isLoading } // isLoading={ isLoading }
fontFamily="heading" // fontFamily="heading"
fontSize="lg" // fontSize="lg"
fontWeight={ 500 } // fontWeight={ 500 }
noLink // noLink
isSafeAddress={ isSafeAddress } // isSafeAddress={ isSafeAddress }
icon={{ color: isSafeAddress ? safeIconColor : undefined }} // icon={{ color: isSafeAddress ? { _light: 'black', _dark: 'white' } : undefined }}
mr={ 4 } // mr={ 4 }
/> // />
{ !isLoading && addressQuery.data?.is_contract && addressQuery.data.token && // { !isLoading && addressQuery.data?.is_contract && addressQuery.data.token &&
<AddressAddToWallet token={ addressQuery.data.token } variant="button"/> } // <AddressAddToWallet token={ addressQuery.data.token } variant="button"/> }
{ !isLoading && !addressQuery.data?.is_contract && config.features.account.isEnabled && ( // { !isLoading && !addressQuery.data?.is_contract && config.features.account.isEnabled && (
<AddressFavoriteButton hash={ hash } watchListId={ addressQuery.data?.watchlist_address_id }/> // <AddressFavoriteButton hash={ hash } watchListId={ addressQuery.data?.watchlist_address_id }/>
) } // ) }
<AddressQrCode address={{ hash: addressQuery.data?.filecoin?.robust ?? checkSummedHash }} isLoading={ isLoading }/> // <AddressQrCode address={{ hash: addressQuery.data?.filecoin?.robust ?? checkSummedHash }} isLoading={ isLoading }/>
<AccountActionsMenu isLoading={ isLoading }/> // <AccountActionsMenu isLoading={ isLoading }/>
<HStack ml="auto" gap={ 2 }/> // <HStack ml="auto" gap={ 2 }/>
{ !isLoading && addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled && // { !isLoading && addressQuery.data?.is_contract && addressQuery.data?.is_verified && config.UI.views.address.solidityscanEnabled &&
<SolidityscanReport hash={ hash }/> } // <SolidityscanReport hash={ hash }/> }
{ !isLoading && addressEnsDomainsQuery.data && config.features.nameService.isEnabled && // { !isLoading && addressEnsDomainsQuery.data && config.features.nameService.isEnabled &&
<AddressEnsDomains query={ addressEnsDomainsQuery } addressHash={ hash } mainDomainName={ addressQuery.data?.ens_domain_name }/> } // <AddressEnsDomains query={ addressEnsDomainsQuery } addressHash={ hash } mainDomainName={ addressQuery.data?.ens_domain_name }/> }
<NetworkExplorers type="address" pathParam={ hash.toLowerCase() }/> // <NetworkExplorers type="address" pathParam={ hash.toLowerCase() }/>
</Flex> // </Flex>
); // );
return ( return (
<> <>
...@@ -420,7 +419,7 @@ const AddressPageContent = () => { ...@@ -420,7 +419,7 @@ const AddressPageContent = () => {
title={ `${ addressQuery.data?.is_contract ? 'Contract' : 'Address' } details` } title={ `${ addressQuery.data?.is_contract ? 'Contract' : 'Address' } details` }
backLink={ backLink } backLink={ backLink }
contentAfter={ titleContentAfter } contentAfter={ titleContentAfter }
secondRow={ titleSecondRow } // secondRow={ titleSecondRow }
isLoading={ isLoading } isLoading={ isLoading }
/> />
{ !addressMetadataQuery.isPending && { !addressMetadataQuery.isPending &&
......
...@@ -12,7 +12,7 @@ const ServiceDegradationWarning = ({ isLoading, className }: Props) => { ...@@ -12,7 +12,7 @@ const ServiceDegradationWarning = ({ isLoading, className }: Props) => {
return ( return (
<Alert <Alert
loading={ isLoading } loading={ isLoading }
status="neutral" status="info"
className={ className } className={ className }
startElement={ <Spinner size="sm" my="3px" flexShrink={ 0 }/> } startElement={ <Spinner size="sm" my="3px" flexShrink={ 0 }/> }
> >
......
...@@ -172,7 +172,6 @@ const AddressEntry = (props: EntityProps) => { ...@@ -172,7 +172,6 @@ const AddressEntry = (props: EntityProps) => {
onMouseLeave={ highlightContext?.onMouseLeave } onMouseLeave={ highlightContext?.onMouseLeave }
position="relative" position="relative"
zIndex={ 0 } zIndex={ 0 }
fontWeight="medium"
> >
<Icon { ...partsProps.icon }/> <Icon { ...partsProps.icon }/>
{ props.noLink ? content : <Link { ...partsProps.link }>{ content }</Link> } { props.noLink ? content : <Link { ...partsProps.link }>{ content }</Link> }
......
...@@ -10,7 +10,7 @@ const MaintenanceAlert = () => { ...@@ -10,7 +10,7 @@ const MaintenanceAlert = () => {
} }
return ( return (
<Alert status="neutral" showIcon> <Alert status="info" showIcon>
<Box <Box
dangerouslySetInnerHTML={{ __html: config.UI.maintenanceAlert.message }} dangerouslySetInnerHTML={{ __html: config.UI.maintenanceAlert.message }}
css={{ css={{
......
...@@ -20,8 +20,8 @@ type Props = { ...@@ -20,8 +20,8 @@ type Props = {
filterValue?: AddressFromToFilter; filterValue?: AddressFromToFilter;
enableTimeIncrement?: boolean; enableTimeIncrement?: boolean;
top?: number; top?: number;
sorting: TransactionsSortingValue | undefined; sorting: TransactionsSortingValue;
setSort: (value?: TransactionsSortingValue) => void; setSort: (value: TransactionsSortingValue) => void;
}; };
const TxsWithAPISorting = ({ const TxsWithAPISorting = ({
...@@ -39,7 +39,7 @@ const TxsWithAPISorting = ({ ...@@ -39,7 +39,7 @@ const TxsWithAPISorting = ({
setSort, setSort,
}: Props) => { }: Props) => {
const handleSortChange = React.useCallback((value?: TransactionsSortingValue) => { const handleSortChange = React.useCallback((value: TransactionsSortingValue) => {
setSort(value); setSort(value);
query.onSortingChange(getSortParamsFromValue(value)); query.onSortingChange(getSortParamsFromValue(value));
}, [ setSort, query ]); }, [ setSort, query ]);
......
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