Commit 6e4b3187 authored by tom's avatar tom

token page

parent 359ce166
...@@ -10,37 +10,41 @@ NEXT_PUBLIC_APP_ENV=development ...@@ -10,37 +10,41 @@ NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
# Instance ENVs # Instance ENVs
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_DESKTOP={ "id": "728301", "width": "728", "height": "90" }
NEXT_PUBLIC_AD_ADBUTLER_CONFIG_MOBILE={ "id": "728302", "width": "320", "height": "100" }
NEXT_PUBLIC_AD_BANNER_ADDITIONAL_PROVIDER=adbutler
NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com NEXT_PUBLIC_ADMIN_SERVICE_API_HOST=https://admin-rs.services.blockscout.com
NEXT_PUBLIC_API_BASE_PATH=/ NEXT_PUBLIC_API_BASE_PATH=/
NEXT_PUBLIC_API_HOST=base.blockscout.com NEXT_PUBLIC_API_HOST=base.blockscout.com
NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml NEXT_PUBLIC_API_SPEC_URL=https://raw.githubusercontent.com/blockscout/blockscout-api-v2-swagger/main/swagger.yaml
NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}] NEXT_PUBLIC_CONTRACT_CODE_IDES=[{'title':'Remix IDE','url':'https://remix.ethereum.org/?address={hash}&blockscout={domain}','icon_url':'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/ide-icons/remix.png'}]
NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com NEXT_PUBLIC_CONTRACT_INFO_API_HOST=https://contracts-info.services.blockscout.com
NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'aerodrome'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}] NEXT_PUBLIC_DEFI_DROPDOWN_ITEMS=[{'text':'Swap','icon':'swap','dappId':'rubic'},{'text':'Disperse','icon':'txn_batches_slim','dappId':'smol'},{'text':'Payment link','icon':'payment_link','dappId':'peanut-protocol'},{'text':'Get gas','icon':'gas','dappId':'smol-refuel'}]
NEXT_PUBLIC_DEX_POOLS_ENABLED=true
NEXT_PUBLIC_FAULT_PROOF_ENABLED=true
NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/base-mainnet.json NEXT_PUBLIC_FEATURED_NETWORKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/featured-networks/base-mainnet.json
NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/base-mainnet.json NEXT_PUBLIC_FOOTER_LINKS=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/footer-links/base-mainnet.json
NEXT_PUBLIC_GAME_BADGE_CLAIM_LINK=https://badges.blockscout.com/mint/sherblockHolmesBadge
NEXT_PUBLIC_GAS_REFUEL_PROVIDER_CONFIG={'name': 'Need gas?', 'url_template': 'https://smolrefuel.com/?outboundChain={chainId}&partner=blockscout&utm_source=blockscout&disableBridges=true', 'dapp_id': 'smol-refuel', 'logo': 'https://blockscout-content.s3.amazonaws.com/smolrefuel-logo-action-button.png'}
NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xfd5c5dae7b69fe29e61d19b9943e688aa0f1be1e983c4fba8fe985f90ff69d5f NEXT_PUBLIC_GRAPHIQL_TRANSACTION=0xfd5c5dae7b69fe29e61d19b9943e688aa0f1be1e983c4fba8fe985f90ff69d5f
NEXT_PUBLIC_HAS_CONTRACT_AUDIT_REPORTS=true
NEXT_PUBLIC_HAS_USER_OPS=true NEXT_PUBLIC_HAS_USER_OPS=true
NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs'] NEXT_PUBLIC_HOMEPAGE_CHARTS=['daily_txs']
NEXT_PUBLIC_HOMEPAGE_PLATE_BACKGROUND=linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%) NEXT_PUBLIC_HOMEPAGE_HERO_BANNER_CONFIG={'background':['linear-gradient(136.9deg,rgb(107 94 236) 1.5%,rgb(0 82 255) 56.84%,rgb(82 62 231) 98.54%)']}
NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true NEXT_PUBLIC_IS_ACCOUNT_SUPPORTED=true
NEXT_PUBLIC_LOGOUT_URL=https://basechain.us.auth0.com/v2/logout NEXT_PUBLIC_LOGOUT_URL=https://basechain.us.auth0.com/v2/logout
NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/maxaleks/0d18fc309ff499075127b364cc69306d/raw/2a51f961a8c1b9f884f2ab7eed79d4b69330e1ae/peanut_protocol_banner.html NEXT_PUBLIC_MAINTENANCE_ALERT_MESSAGE=<p>Joined recent campaigns? Mint your Merit Badge <a href="https://badges.blockscout.com?utm_source=instance&utm_medium=base">here</a></p>
NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://base.blockscout.com/apps/peanut-protocol NEXT_PUBLIC_MARKETPLACE_BANNER_CONTENT_URL=https://gist.githubusercontent.com/maikReal/974c47f86a3158c1a86b092ae2f044b3/raw/abcc7e02150cd85d4974503a0357162c0a2c35a9/merits-banner.html
NEXT_PUBLIC_MARKETPLACE_BANNER_LINK_URL=https://swap.blockscout.com?utm_source=blockscout&utm_medium=base
NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json NEXT_PUBLIC_MARKETPLACE_CATEGORIES_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-categories/default.json
NEXT_PUBLIC_MARKETPLACE_ENABLED=true NEXT_PUBLIC_MARKETPLACE_ENABLED=true
NEXT_PUBLIC_MARKETPLACE_RATING_AIRTABLE_BASE_ID=appGkvtmKI7fXE4Vs
NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json NEXT_PUBLIC_MARKETPLACE_SECURITY_REPORTS_URL=https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-security-reports/default.json
NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL NEXT_PUBLIC_MARKETPLACE_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form NEXT_PUBLIC_MARKETPLACE_SUGGEST_IDEAS_FORM=https://airtable.com/appiy5yijZpMMSKjT/pag3t82DUCyhGRZZO/form
NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com NEXT_PUBLIC_METADATA_SERVICE_API_HOST=https://metadata.services.blockscout.com
NEXT_PUBLIC_METASUITES_ENABLED=true NEXT_PUBLIC_METASUITES_ENABLED=true
NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'dapp_id': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview?utm_source=blockscout&utm_medium=address', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'}] NEXT_PUBLIC_MULTICHAIN_BALANCE_PROVIDER_CONFIG=[{'name': 'zerion', 'url_template': 'https://app.zerion.io/{address}/overview', 'logo': 'https://raw.githubusercontent.com/blockscout/frontend-configs/main/configs/marketplace-logos/zerion.svg'},{'name': 'zapper', 'url_template': 'https://zapper.xyz/account/{address}', 'logo': 'https://blockscout-content.s3.amazonaws.com/zapper-icon.png'}]
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/apps'] NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/pools']
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18 NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
...@@ -59,8 +63,10 @@ NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/ ...@@ -59,8 +63,10 @@ NEXT_PUBLIC_ROLLUP_L1_BASE_URL=https://eth.blockscout.com/
NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.base.org/withdraw NEXT_PUBLIC_ROLLUP_L2_WITHDRAWAL_URL=https://bridge.base.org/withdraw
NEXT_PUBLIC_ROLLUP_TYPE=optimistic NEXT_PUBLIC_ROLLUP_TYPE=optimistic
NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-base.safe.global NEXT_PUBLIC_SAFE_TX_SERVICE_URL=https://safe-transaction-base.safe.global
NEXT_PUBLIC_STATS_API_HOST=https://stats-l2-base-mainnet.k8s-prod-1.blockscout.com NEXT_PUBLIC_STATS_API_HOST=https://stats-l2-base-mainnet.k8s-prod-2.blockscout.com
NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout NEXT_PUBLIC_TRANSACTION_INTERPRETATION_PROVIDER=blockscout
NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar NEXT_PUBLIC_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com NEXT_PUBLIC_VIEWS_NFT_MARKETPLACES=[{'name':'OpenSea','collection_url':'https://opensea.io/assets/base/{hash}','instance_url':'https://opensea.io/assets/base/{hash}/{id}','logo_url':'https://opensea.io/static/images/logos/opensea-logo.svg'}]
\ No newline at end of file NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
NEXT_PUBLIC_XSTAR_SCORE_URL=https://docs.xname.app/the-solution-adaptive-proof-of-humanity-on-blockchain/xhs-scoring-algorithm?utm_source=blockscout&utm_medium=address
\ No newline at end of file
...@@ -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 Token from 'ui/pages/Token'; import Token from 'ui/pages/Token';
const pathname: Route['pathname'] = '/token/[hash]'; const pathname: Route['pathname'] = '/token/[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 }>
{ /* <Token/> */ } <Token/>
</PageNextJs> </PageNextJs>
); );
}; };
......
...@@ -4,9 +4,9 @@ import { useRouter } from 'next/router'; ...@@ -4,9 +4,9 @@ import { useRouter } from 'next/router';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import type { SocketMessage } from 'lib/socket/types'; import type { SocketMessage } from 'lib/socket/types';
import type { TabItemRegular } from 'toolkit/components/AdaptiveTabs/types';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
import type { PaginationParams } from 'ui/shared/pagination/types'; import type { PaginationParams } from 'ui/shared/pagination/types';
import type { RoutedTab } from 'ui/shared/Tabs/types';
import config from 'configs/app'; import config from 'configs/app';
import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery'; import useApiQuery, { getResourceKey } from 'lib/api/useApiQuery';
...@@ -20,6 +20,7 @@ import * as addressStubs from 'stubs/address'; ...@@ -20,6 +20,7 @@ import * as addressStubs from 'stubs/address';
import * as tokenStubs from 'stubs/token'; import * as tokenStubs from 'stubs/token';
import { getTokenHoldersStub } from 'stubs/token'; import { getTokenHoldersStub } from 'stubs/token';
import { generateListStub } from 'stubs/utils'; import { generateListStub } from 'stubs/utils';
import RoutedTabs from 'toolkit/components/RoutedTabs/RoutedTabs';
import AddressContract from 'ui/address/AddressContract'; import AddressContract from 'ui/address/AddressContract';
import AddressCsvExportLink from 'ui/address/AddressCsvExportLink'; import AddressCsvExportLink from 'ui/address/AddressCsvExportLink';
import useContractTabs from 'ui/address/contract/useContractTabs'; import useContractTabs from 'ui/address/contract/useContractTabs';
...@@ -28,7 +29,6 @@ import TextAd from 'ui/shared/ad/TextAd'; ...@@ -28,7 +29,6 @@ import TextAd from 'ui/shared/ad/TextAd';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
import Pagination from 'ui/shared/pagination/Pagination'; import Pagination from 'ui/shared/pagination/Pagination';
import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages'; import useQueryWithPages from 'ui/shared/pagination/useQueryWithPages';
import RoutedTabs from 'ui/shared/Tabs/RoutedTabs';
import TokenDetails from 'ui/token/TokenDetails'; import TokenDetails from 'ui/token/TokenDetails';
import TokenHolders from 'ui/token/TokenHolders/TokenHolders'; import TokenHolders from 'ui/token/TokenHolders/TokenHolders';
import TokenInventory from 'ui/token/TokenInventory'; import TokenInventory from 'ui/token/TokenInventory';
...@@ -161,7 +161,7 @@ const TokenPageContent = () => { ...@@ -161,7 +161,7 @@ const TokenPageContent = () => {
const isLoading = tokenQuery.isPlaceholderData || addressQuery.isPlaceholderData; const isLoading = tokenQuery.isPlaceholderData || addressQuery.isPlaceholderData;
const contractTabs = useContractTabs(addressQuery.data, addressQuery.isPlaceholderData); const contractTabs = useContractTabs(addressQuery.data, addressQuery.isPlaceholderData);
const tabs: Array<RoutedTab> = [ const tabs: Array<TabItemRegular> = [
hasInventoryTab ? { hasInventoryTab ? {
id: 'inventory', id: 'inventory',
title: 'Inventory', title: 'Inventory',
...@@ -212,7 +212,7 @@ const TokenPageContent = () => { ...@@ -212,7 +212,7 @@ const TokenPageContent = () => {
pagination = inventoryQuery.pagination; pagination = inventoryQuery.pagination;
} }
const tabListProps = React.useCallback(({ isSticky, activeTabIndex }: { isSticky: boolean; activeTabIndex: number }) => { const tabListProps = React.useCallback(() => {
if (isMobile) { if (isMobile) {
return { mt: 8 }; return { mt: 8 };
} }
...@@ -221,7 +221,6 @@ const TokenPageContent = () => { ...@@ -221,7 +221,6 @@ const TokenPageContent = () => {
pt: 6, pt: 6,
pb: 6, pb: 6,
marginBottom: 0, marginBottom: 0,
boxShadow: activeTabIndex === 2 && isSticky ? 'action_bar' : 'none',
}; };
}, [ isMobile ]); }, [ isMobile ]);
...@@ -257,7 +256,7 @@ const TokenPageContent = () => { ...@@ -257,7 +256,7 @@ const TokenPageContent = () => {
<RoutedTabs <RoutedTabs
tabs={ tabs } tabs={ tabs }
tabListProps={ tabListProps } listProps={ tabListProps }
rightSlot={ tabsRightSlot } rightSlot={ tabsRightSlot }
rightSlotProps={ TABS_RIGHT_SLOT_PROPS } rightSlotProps={ TABS_RIGHT_SLOT_PROPS }
stickyEnabled={ !isMobile } stickyEnabled={ !isMobile }
......
...@@ -82,6 +82,7 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => { ...@@ -82,6 +82,7 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => {
onClick={ handleLinkClick } onClick={ handleLinkClick }
noIcon noIcon
cursor={ hasLink ? 'pointer' : 'default' } cursor={ hasLink ? 'pointer' : 'default' }
{ ...rest }
> >
<Tag <Tag
bg={ data.meta?.bgColor } bg={ data.meta?.bgColor }
...@@ -92,7 +93,6 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => { ...@@ -92,7 +93,6 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => {
endElementProps={ linkParams?.type === 'external' ? { ml: -1 } : undefined } endElementProps={ linkParams?.type === 'external' ? { ml: -1 } : undefined }
_hover={ hasLink ? { opacity: 0.76 } : undefined } _hover={ hasLink ? { opacity: 0.76 } : undefined }
variant={ hasLink ? 'clickable' : 'subtle' } variant={ hasLink ? 'clickable' : 'subtle' }
{ ...rest }
> >
{ prefix }{ name } { prefix }{ name }
</Tag> </Tag>
......
...@@ -45,7 +45,7 @@ const EntityTags = ({ tags, className, isLoading }: Props) => { ...@@ -45,7 +45,7 @@ const EntityTags = ({ tags, className, isLoading }: Props) => {
+{ tags.length - visibleNum } +{ tags.length - visibleNum }
</Badge> </Badge>
</PopoverTrigger> </PopoverTrigger>
<PopoverContent maxW="300px"> <PopoverContent maxW="300px" w="fit-content">
<PopoverBody> <PopoverBody>
<Flex columnGap={ 2 } rowGap={ 2 } flexWrap="wrap"> <Flex columnGap={ 2 } rowGap={ 2 } flexWrap="wrap">
{ tags.slice(visibleNum).map((tag) => <EntityTag key={ tag.slug } data={ tag }/>) } { tags.slice(visibleNum).map((tag) => <EntityTag key={ tag.slug } data={ tag }/>) }
......
import {
PopoverTrigger, PopoverContent, PopoverBody,
Modal, ModalContent, ModalCloseButton,
useDisclosure,
Button,
} from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import Popover from 'ui/shared/chakra/Popover'; import { Button } from 'toolkit/chakra/button';
import { DialogRoot, DialogContent, DialogTrigger, DialogHeader } from 'toolkit/chakra/dialog';
import IconSvg from './IconSvg'; import { PopoverBody, PopoverContent, PopoverRoot, PopoverTrigger } from 'toolkit/chakra/popover';
import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
children: React.ReactNode; children: React.ReactNode;
...@@ -17,21 +12,16 @@ interface Props { ...@@ -17,21 +12,16 @@ interface Props {
const InfoButton = ({ children }: Props) => { const InfoButton = ({ children }: Props) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const { isOpen, onToggle, onClose } = useDisclosure();
const triggerButton = ( const triggerButton = (
<Button <Button
size="sm" size="sm"
variant="outline" variant="dropdown"
colorScheme="gray" gap={ 0 }
onClick={ onToggle }
isActive={ isOpen }
aria-label="Show info" aria-label="Show info"
fontWeight={ 500 } fontWeight={ 500 }
lineHeight={ 6 }
pl={ 1 } pl={ 1 }
pr={ isMobile ? 1 : 2 } pr={ isMobile ? 1 : 2 }
h="32px"
> >
<IconSvg name="info" boxSize={ 6 } mr={ isMobile ? 0 : 1 }/> <IconSvg name="info" boxSize={ 6 } mr={ isMobile ? 0 : 1 }/>
{ !isMobile && <span>Info</span> } { !isMobile && <span>Info</span> }
...@@ -40,29 +30,29 @@ const InfoButton = ({ children }: Props) => { ...@@ -40,29 +30,29 @@ const InfoButton = ({ children }: Props) => {
if (isMobile) { if (isMobile) {
return ( return (
<> <DialogRoot size="full">
{ triggerButton } <DialogTrigger>
<Modal isOpen={ isOpen } onClose={ onClose } size="full"> { triggerButton }
<ModalContent> </DialogTrigger>
<ModalCloseButton/> <DialogContent>
{ children } <DialogHeader/>
</ModalContent> { children }
</Modal> </DialogContent>
</> </DialogRoot>
); );
} }
return ( return (
<Popover isOpen={ isOpen } onClose={ onClose } placement="bottom-start" isLazy> <PopoverRoot>
<PopoverTrigger> <PopoverTrigger>
{ triggerButton } { triggerButton }
</PopoverTrigger> </PopoverTrigger>
<PopoverContent w="500px"> <PopoverContent w="500px">
<PopoverBody px={ 6 } py={ 5 }> <PopoverBody>
{ children } { children }
</PopoverBody> </PopoverBody>
</PopoverContent> </PopoverContent>
</Popover> </PopoverRoot>
); );
}; };
......
import { Tooltip, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { IconButton } from 'toolkit/chakra/icon-button';
import { Tooltip } from 'toolkit/chakra/tooltip';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
type Props = { type Props = {
...@@ -8,22 +9,14 @@ type Props = { ...@@ -8,22 +9,14 @@ type Props = {
}; };
const ResetIconButton = ({ onClick }: Props) => { const ResetIconButton = ({ onClick }: Props) => {
const resetTokenIconColor = useColorModeValue('blue.600', 'blue.300');
const resetTokenIconHoverColor = useColorModeValue('blue.400', 'blue.200');
return ( return (
<Tooltip label="Reset filter"> <Tooltip content="Reset filter">
<Flex> <IconButton ml={ 1 } variant="link" onClick={ onClick }>
<IconSvg <IconSvg
name="cross" name="cross"
boxSize={ 5 } boxSize={ 5 }
ml={ 1 }
color={ resetTokenIconColor }
cursor="pointer"
_hover={{ color: resetTokenIconHoverColor }}
onClick={ onClick }
/> />
</Flex> </IconButton>
</Tooltip> </Tooltip>
); );
}; };
......
import { Box, Grid, Link } from '@chakra-ui/react'; import { Box, Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
...@@ -14,10 +14,11 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError'; ...@@ -14,10 +14,11 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import useIsMounted from 'lib/hooks/useIsMounted'; import useIsMounted from 'lib/hooks/useIsMounted';
import { TOKEN_COUNTERS } from 'stubs/token'; import { TOKEN_COUNTERS } from 'stubs/token';
import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import type { TokenTabs } from 'ui/pages/Token'; import type { TokenTabs } from 'ui/pages/Token';
import AppActionButton from 'ui/shared/AppActionButton/AppActionButton'; import AppActionButton from 'ui/shared/AppActionButton/AppActionButton';
import useAppActionData from 'ui/shared/AppActionButton/useAppActionData'; import useAppActionData from 'ui/shared/AppActionButton/useAppActionData';
import Skeleton from 'ui/shared/chakra/Skeleton';
import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo'; import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import DetailedInfoSponsoredItem from 'ui/shared/DetailedInfo/DetailedInfoSponsoredItem'; import DetailedInfoSponsoredItem from 'ui/shared/DetailedInfo/DetailedInfoSponsoredItem';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
...@@ -65,11 +66,9 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -65,11 +66,9 @@ const TokenDetails = ({ tokenQuery }: Props) => {
const tab: TokenTabs = item === 'token_holders_count' ? 'holders' : 'token_transfers'; const tab: TokenTabs = item === 'token_holders_count' ? 'holders' : 'token_transfers';
return ( return (
<Skeleton isLoaded={ !tokenCountersQuery.isPlaceholderData }> <Link onClick={ changeUrlAndScroll(tab) } loading={ tokenCountersQuery.isPlaceholderData }>
<Link onClick={ changeUrlAndScroll(tab) }> { Number(itemValue).toLocaleString() }
{ Number(itemValue).toLocaleString() } </Link>
</Link>
</Skeleton>
); );
}, [ tokenCountersQuery.data, tokenCountersQuery.isPlaceholderData, changeUrlAndScroll ]); }, [ tokenCountersQuery.data, tokenCountersQuery.isPlaceholderData, changeUrlAndScroll ]);
...@@ -112,7 +111,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -112,7 +111,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Price Price
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !tokenQuery.isPlaceholderData } display="inline-block"> <Skeleton loading={ tokenQuery.isPlaceholderData } display="inline-block">
<span>{ `$${ Number(exchangeRate).toLocaleString(undefined, { minimumSignificantDigits: 4 }) }` }</span> <span>{ `$${ Number(exchangeRate).toLocaleString(undefined, { minimumSignificantDigits: 4 }) }` }</span>
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
...@@ -128,7 +127,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -128,7 +127,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Fully diluted market cap Fully diluted market cap
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !tokenQuery.isPlaceholderData } display="inline-block"> <Skeleton loading={ tokenQuery.isPlaceholderData } display="inline-block">
<span>{ `$${ BigNumber(marketCap).toFormat() }` }</span> <span>{ `$${ BigNumber(marketCap).toFormat() }` }</span>
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
...@@ -146,7 +145,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -146,7 +145,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
wordBreak="break-word" wordBreak="break-word"
whiteSpace="pre-wrap" whiteSpace="pre-wrap"
> >
<Skeleton isLoaded={ !tokenQuery.isPlaceholderData } w="100%" display="flex"> <Skeleton loading={ tokenQuery.isPlaceholderData } w="100%" display="flex">
<TruncatedValue value={ totalSupplyValue || '0' } maxW="80%" flexShrink={ 0 }/> <TruncatedValue value={ totalSupplyValue || '0' } maxW="80%" flexShrink={ 0 }/>
<Box flexShrink={ 0 }> </Box> <Box flexShrink={ 0 }> </Box>
<TruncatedValue value={ symbol || '' }/> <TruncatedValue value={ symbol || '' }/>
...@@ -160,7 +159,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -160,7 +159,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Holders Holders
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !tokenCountersQuery.isPlaceholderData }> <Skeleton loading={ tokenCountersQuery.isPlaceholderData }>
{ countersItem('token_holders_count') } { countersItem('token_holders_count') }
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
...@@ -172,7 +171,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -172,7 +171,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Transfers Transfers
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !tokenCountersQuery.isPlaceholderData }> <Skeleton loading={ tokenCountersQuery.isPlaceholderData }>
{ countersItem('transfers_count') } { countersItem('transfers_count') }
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
...@@ -186,7 +185,7 @@ const TokenDetails = ({ tokenQuery }: Props) => { ...@@ -186,7 +185,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Decimals Decimals
</DetailedInfo.ItemLabel> </DetailedInfo.ItemLabel>
<DetailedInfo.ItemValue> <DetailedInfo.ItemValue>
<Skeleton isLoaded={ !tokenQuery.isPlaceholderData } minW={ 6 }> <Skeleton loading={ tokenQuery.isPlaceholderData } minW={ 6 }>
{ decimals } { decimals }
</Skeleton> </Skeleton>
</DetailedInfo.ItemValue> </DetailedInfo.ItemValue>
......
...@@ -37,11 +37,13 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props ...@@ -37,11 +37,13 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
const actionBar = isMobile && holdersQuery.pagination.isVisible && ( const actionBar = isMobile && holdersQuery.pagination.isVisible && (
<ActionBar mt={ -6 }> <ActionBar mt={ -6 }>
<AddressCsvExportLink { token && (
address={ token?.address } <AddressCsvExportLink
params={{ type: 'holders' }} address={ token.address }
isLoading={ holdersQuery.pagination.isLoading } params={{ type: 'holders' }}
/> isLoading={ holdersQuery.pagination.isLoading }
/>
) }
<Pagination ml="auto" { ...holdersQuery.pagination }/> <Pagination ml="auto" { ...holdersQuery.pagination }/>
</ActionBar> </ActionBar>
); );
...@@ -54,7 +56,7 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props ...@@ -54,7 +56,7 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
<TokenHoldersTable <TokenHoldersTable
data={ items } data={ items }
token={ token } token={ token }
top={ holdersQuery.pagination.isVisible ? TABS_HEIGHT : 0 } top={ TABS_HEIGHT }
isLoading={ holdersQuery.isPlaceholderData } isLoading={ holdersQuery.isPlaceholderData }
/> />
</Box> </Box>
...@@ -71,11 +73,12 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props ...@@ -71,11 +73,12 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
return ( return (
<DataListDisplay <DataListDisplay
isError={ holdersQuery.isError } isError={ holdersQuery.isError }
items={ holdersQuery.data?.items } itemsNum={ holdersQuery.data?.items.length }
emptyText="There are no holders for this token." emptyText="There are no holders for this token."
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
); );
}; };
......
...@@ -3,7 +3,7 @@ import React from 'react'; ...@@ -3,7 +3,7 @@ import React from 'react';
import type { TokenHolder, TokenInfo } from 'types/api/token'; import type { TokenHolder, TokenInfo } from 'types/api/token';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid'; import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
import Utilization from 'ui/shared/Utilization/Utilization'; import Utilization from 'ui/shared/Utilization/Utilization';
...@@ -33,7 +33,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => { ...@@ -33,7 +33,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => {
<> <>
<ListItemMobileGrid.Label isLoading={ isLoading }>ID#</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>ID#</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ holder.token_id } { holder.token_id }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
...@@ -42,7 +42,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => { ...@@ -42,7 +42,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Quantity</ListItemMobileGrid.Label> <ListItemMobileGrid.Label isLoading={ isLoading }>Quantity</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value> <ListItemMobileGrid.Value>
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ quantity } { quantity }
</Skeleton> </Skeleton>
</ListItemMobileGrid.Value> </ListItemMobileGrid.Value>
......
import { Table, Tbody, Tr, Th } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenHolder, TokenInfo } from 'types/api/token'; import type { TokenHolder, TokenInfo } from 'types/api/token';
import { default as Thead } from 'ui/shared/TheadSticky'; import { TableBody, TableColumnHeader, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import TokenHoldersTableItem from 'ui/token/TokenHolders/TokenHoldersTableItem'; import TokenHoldersTableItem from 'ui/token/TokenHolders/TokenHoldersTableItem';
interface Props { interface Props {
...@@ -15,21 +14,21 @@ interface Props { ...@@ -15,21 +14,21 @@ interface Props {
const TokenHoldersTable = ({ data, token, top, isLoading }: Props) => { const TokenHoldersTable = ({ data, token, top, isLoading }: Props) => {
return ( return (
<Table layout="auto"> <TableRoot tableLayout="auto">
<Thead top={ top }> <TableHeaderSticky top={ top }>
<Tr> <TableRow>
<Th>Holder</Th> <TableColumnHeader>Holder</TableColumnHeader>
{ (token.type === 'ERC-1155' || token.type === 'ERC-404') && <Th>ID#</Th> } { (token.type === 'ERC-1155' || token.type === 'ERC-404') && <TableColumnHeader>ID#</TableColumnHeader> }
<Th isNumeric>Quantity</Th> <TableColumnHeader isNumeric>Quantity</TableColumnHeader>
{ token.total_supply && token.type !== 'ERC-404' && <Th isNumeric width="175px">Percentage</Th> } { token.total_supply && token.type !== 'ERC-404' && <TableColumnHeader isNumeric width="175px">Percentage</TableColumnHeader> }
</Tr> </TableRow>
</Thead> </TableHeaderSticky>
<Tbody> <TableBody>
{ data.map((item, index) => ( { data.map((item, index) => (
<TokenHoldersTableItem key={ item.address.hash + (isLoading ? index : '') } holder={ item } token={ token } isLoading={ isLoading }/> <TokenHoldersTableItem key={ item.address.hash + (isLoading ? index : '') } holder={ item } token={ token } isLoading={ isLoading }/>
)) } )) }
</Tbody> </TableBody>
</Table> </TableRoot>
); );
}; };
......
import { Tr, Td } from '@chakra-ui/react';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import React from 'react'; import React from 'react';
import type { TokenHolder, TokenInfo } from 'types/api/token'; import type { TokenHolder, TokenInfo } from 'types/api/token';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import Utilization from 'ui/shared/Utilization/Utilization'; import Utilization from 'ui/shared/Utilization/Utilization';
...@@ -18,38 +18,38 @@ const TokenTransferTableItem = ({ holder, token, isLoading }: Props) => { ...@@ -18,38 +18,38 @@ const TokenTransferTableItem = ({ holder, token, isLoading }: Props) => {
const quantity = BigNumber(holder.value).div(BigNumber(10 ** Number(token.decimals))).toFormat(); const quantity = BigNumber(holder.value).div(BigNumber(10 ** Number(token.decimals))).toFormat();
return ( return (
<Tr> <TableRow>
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<AddressEntity <AddressEntity
address={ holder.address } address={ holder.address }
isLoading={ isLoading } isLoading={ isLoading }
flexGrow={ 1 } flexGrow={ 1 }
fontWeight="700" fontWeight="700"
/> />
</Td> </TableCell>
{ (token.type === 'ERC-1155' || token.type === 'ERC-404') && 'token_id' in holder && ( { (token.type === 'ERC-1155' || token.type === 'ERC-404') && 'token_id' in holder && (
<Td verticalAlign="middle"> <TableCell verticalAlign="middle">
<Skeleton isLoaded={ !isLoading } display="inline-block"> <Skeleton loading={ isLoading } display="inline-block">
{ 'token_id' in holder && holder.token_id } { 'token_id' in holder && holder.token_id }
</Skeleton> </Skeleton>
</Td> </TableCell>
) } ) }
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Skeleton isLoaded={ !isLoading } display="inline-block" wordBreak="break-word"> <Skeleton loading={ isLoading } display="inline-block" wordBreak="break-word">
{ quantity } { quantity }
</Skeleton> </Skeleton>
</Td> </TableCell>
{ token.total_supply && token.type !== 'ERC-404' && ( { token.total_supply && token.type !== 'ERC-404' && (
<Td verticalAlign="middle" isNumeric> <TableCell verticalAlign="middle" isNumeric>
<Utilization <Utilization
value={ BigNumber(holder.value).div(BigNumber(token.total_supply)).dp(4).toNumber() } value={ BigNumber(holder.value).div(BigNumber(token.total_supply)).dp(4).toNumber() }
colorScheme="green" colorScheme="green"
display="inline-flex" display="inline-flex"
isLoading={ isLoading } isLoading={ isLoading }
/> />
</Td> </TableCell>
) } ) }
</Tr> </TableRow>
); );
}; };
......
...@@ -88,15 +88,16 @@ const TokenInventory = ({ inventoryQuery, tokenQuery, ownerFilter, shouldRender ...@@ -88,15 +88,16 @@ const TokenInventory = ({ inventoryQuery, tokenQuery, ownerFilter, shouldRender
return ( return (
<DataListDisplay <DataListDisplay
isError={ inventoryQuery.isError } isError={ inventoryQuery.isError }
items={ items } itemsNum={ items?.length }
emptyText="There are no tokens." emptyText="There are no tokens."
filterProps={{ filterProps={{
hasActiveFilters: Boolean(ownerFilter), hasActiveFilters: Boolean(ownerFilter),
emptyFilteredText: 'No tokens found for the selected owner.', emptyFilteredText: 'No tokens found for the selected owner.',
}} }}
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
); );
}; };
......
import { Box, Flex, Text, Link, useColorModeValue } from '@chakra-ui/react'; import { Box, Flex, Text } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo, TokenInstance } from 'types/api/token'; import type { TokenInfo, TokenInstance } from 'types/api/token';
...@@ -6,9 +6,9 @@ import type { TokenInfo, TokenInstance } from 'types/api/token'; ...@@ -6,9 +6,9 @@ import type { TokenInfo, TokenInstance } from 'types/api/token';
import { route } from 'nextjs-routes'; import { route } from 'nextjs-routes';
import useIsMobile from 'lib/hooks/useIsMobile'; import useIsMobile from 'lib/hooks/useIsMobile';
import Skeleton from 'ui/shared/chakra/Skeleton'; import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressEntity from 'ui/shared/entities/address/AddressEntity'; import AddressEntity from 'ui/shared/entities/address/AddressEntity';
import LinkInternal from 'ui/shared/links/LinkInternal';
import NftMedia from 'ui/shared/nft/NftMedia'; import NftMedia from 'ui/shared/nft/NftMedia';
import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip'; import TruncatedTextTooltip from 'ui/shared/TruncatedTextTooltip';
...@@ -33,38 +33,37 @@ const TokenInventoryItem = ({ item, token, isLoading }: Props) => { ...@@ -33,38 +33,37 @@ const TokenInventoryItem = ({ item, token, isLoading }: Props) => {
<Box <Box
w={{ base: '100%', lg: '210px' }} w={{ base: '100%', lg: '210px' }}
border="1px solid" border="1px solid"
borderColor={ useColorModeValue('blackAlpha.100', 'whiteAlpha.200') } borderColor={{ _light: 'blackAlpha.100', _dark: 'whiteAlpha.200' }}
borderRadius="12px" borderRadius="12px"
p="10px" p="10px"
fontSize="sm" textStyle="sm"
fontWeight={ 500 } fontWeight={ 500 }
lineHeight="20px"
> >
<Link href={ isLoading ? undefined : url }> <Link href={ isLoading ? undefined : url } display="inline">
{ mediaElement } { mediaElement }
</Link> </Link>
{ item.id && ( { item.id && (
<Flex mb={ 2 } ml={ 1 }> <Flex mb={ 2 } ml={ 1 }>
<Text whiteSpace="pre" variant="secondary">ID# </Text> <Text whiteSpace="pre" color="text.secondary">ID# </Text>
<TruncatedTextTooltip label={ item.id }> <TruncatedTextTooltip label={ item.id }>
<Skeleton isLoaded={ !isLoading } overflow="hidden"> <Skeleton loading={ isLoading } overflow="hidden">
<LinkInternal <Link
overflow="hidden" overflow="hidden"
textOverflow="ellipsis" textOverflow="ellipsis"
whiteSpace="nowrap" whiteSpace="nowrap"
display="block" display="block"
isLoading={ isLoading } loading={ isLoading }
href={ url } href={ url }
> >
{ item.id } { item.id }
</LinkInternal> </Link>
</Skeleton> </Skeleton>
</TruncatedTextTooltip> </TruncatedTextTooltip>
</Flex> </Flex>
) } ) }
{ item.owner && ( { item.owner && (
<Flex mb={ 2 } ml={ 1 }> <Flex mb={ 2 } ml={ 1 }>
<Text whiteSpace="pre" variant="secondary" mr={ 2 } lineHeight="24px">Owner</Text> <Text whiteSpace="pre" color="text.secondary" mr={ 2 } lineHeight="24px">Owner</Text>
<AddressEntity <AddressEntity
address={ item.owner } address={ item.owner }
isLoading={ isLoading } isLoading={ isLoading }
......
import { Image, Link, Tooltip } 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 config from 'configs/app'; import config from 'configs/app';
import { Image } from 'toolkit/chakra/image';
import { Link } from 'toolkit/chakra/link';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { Tooltip } from 'toolkit/chakra/tooltip';
import AppActionButton from 'ui/shared/AppActionButton/AppActionButton'; import AppActionButton from 'ui/shared/AppActionButton/AppActionButton';
import Skeleton from 'ui/shared/chakra/Skeleton';
import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo'; import * as DetailedInfo from 'ui/shared/DetailedInfo/DetailedInfo';
import TextSeparator from 'ui/shared/TextSeparator'; import TextSeparator from 'ui/shared/TextSeparator';
...@@ -33,14 +35,14 @@ const TokenNftMarketplaces = ({ hash, id, isLoading, appActionData, source }: Pr ...@@ -33,14 +35,14 @@ const TokenNftMarketplaces = ({ hash, id, isLoading, appActionData, source }: Pr
<DetailedInfo.ItemValue <DetailedInfo.ItemValue
py={ appActionData ? '1px' : '6px' } py={ appActionData ? '1px' : '6px' }
> >
<Skeleton isLoaded={ !isLoading } display="flex" columnGap={ 3 } flexWrap="wrap" alignItems="center"> <Skeleton loading={ isLoading } display="flex" columnGap={ 3 } flexWrap="wrap" alignItems="center">
{ config.UI.views.nft.marketplaces.map((item) => { { config.UI.views.nft.marketplaces.map((item) => {
const hrefTemplate = id ? item.instance_url : item.collection_url; const hrefTemplate = id ? item.instance_url : item.collection_url;
const href = hrefTemplate.replace('{id}', id || '').replace('{hash}', hash || ''); const href = hrefTemplate.replace('{id}', id || '').replace('{hash}', hash || '');
return ( return (
<Tooltip label={ `View on ${ item.name }` } key={ item.name }> <Tooltip content={ `View on ${ item.name }` } key={ item.name }>
<Link href={ href } target="_blank"> <Link href={ href } target="_blank">
<Image <Image
src={ item.logo_url } src={ item.logo_url }
......
import { Box, Flex, Tooltip, useToken } from '@chakra-ui/react'; import { Flex, useToken } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query'; import type { UseQueryResult } from '@tanstack/react-query';
import React from 'react'; import React from 'react';
...@@ -12,6 +12,7 @@ import type { ResourceError } from 'lib/api/resources'; ...@@ -12,6 +12,7 @@ import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery'; import useApiQuery from 'lib/api/useApiQuery';
import { useAppContext } from 'lib/contexts/app'; import { useAppContext } from 'lib/contexts/app';
import { getTokenTypeName } from 'lib/token/tokenTypes'; import { getTokenTypeName } from 'lib/token/tokenTypes';
import { Tooltip } from 'toolkit/chakra/tooltip';
import AddressMetadataAlert from 'ui/address/details/AddressMetadataAlert'; import AddressMetadataAlert from 'ui/address/details/AddressMetadataAlert';
import AddressQrCode from 'ui/address/details/AddressQrCode'; import AddressQrCode from 'ui/address/details/AddressQrCode';
import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu'; import AccountActionsMenu from 'ui/shared/AccountActionsMenu/AccountActionsMenu';
...@@ -66,8 +67,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => { ...@@ -66,8 +67,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
}; };
}, [ appProps.referrer ]); }, [ appProps.referrer ]);
const bridgedTokenTagBgColor = useToken('colors', 'blue.500'); const [ bridgedTokenTagBgColor ] = useToken('colors', 'blue.500');
const bridgedTokenTagTextColor = useToken('colors', 'white'); const [ bridgedTokenTagTextColor ] = useToken('colors', 'white');
const tags: Array<EntityTag> = React.useMemo(() => { const tags: Array<EntityTag> = React.useMemo(() => {
return [ return [
...@@ -105,10 +106,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => { ...@@ -105,10 +106,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
const contentAfter = ( const contentAfter = (
<> <>
{ verifiedInfoQuery.data?.tokenAddress && ( { verifiedInfoQuery.data?.tokenAddress && (
<Tooltip label={ `Information on this token has been verified by ${ config.chain.name }` }> <Tooltip content={ `Information on this token has been verified by ${ config.chain.name }` }>
<Box boxSize={ 6 }> <IconSvg name="certified" color="green.500" boxSize={ 6 } cursor="pointer"/>
<IconSvg name="certified" color="green.500" boxSize={ 6 } cursor="pointer"/>
</Box>
</Tooltip> </Tooltip>
) } ) }
<EntityTags <EntityTags
...@@ -131,7 +130,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => { ...@@ -131,7 +130,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
/> />
) } ) }
{ !isLoading && tokenQuery.data && <AddressAddToWallet token={ tokenQuery.data } variant="button"/> } { !isLoading && tokenQuery.data && <AddressAddToWallet token={ tokenQuery.data } variant="button"/> }
<AddressQrCode address={ addressQuery.data } isLoading={ isLoading }/> { addressQuery.data && <AddressQrCode hash={ addressQuery.data.hash } isLoading={ isLoading }/> }
<AccountActionsMenu isLoading={ isLoading }/> <AccountActionsMenu isLoading={ isLoading }/>
<Flex ml={{ base: 0, lg: 'auto' }} columnGap={ 2 } flexGrow={{ base: 1, lg: 0 }}> <Flex ml={{ base: 0, lg: 'auto' }} columnGap={ 2 } flexGrow={{ base: 1, lg: 0 }}>
<TokenVerifiedInfo verifiedInfoQuery={ verifiedInfoQuery }/> <TokenVerifiedInfo verifiedInfoQuery={ verifiedInfoQuery }/>
......
...@@ -59,7 +59,7 @@ const Content = ({ data }: Props) => { ...@@ -59,7 +59,7 @@ const Content = ({ data }: Props) => {
<Flex fontSize="sm" flexDir="column" rowGap={ 5 }> <Flex fontSize="sm" flexDir="column" rowGap={ 5 }>
{ (description || docs || support) && ( { (description || docs || support) && (
<div> <div>
<Text variant="secondary" fontSize="xs">Description and support info</Text> <Text color="text.secondary" fontSize="xs">Description and support info</Text>
{ description } { description }
{ (docs || support) && ( { (docs || support) && (
<Flex alignItems="center" flexWrap="wrap" columnGap={ 6 } mt={ 3 }> <Flex alignItems="center" flexWrap="wrap" columnGap={ 6 } mt={ 3 }>
...@@ -71,7 +71,7 @@ const Content = ({ data }: Props) => { ...@@ -71,7 +71,7 @@ const Content = ({ data }: Props) => {
) } ) }
{ socialLinks.length > 0 && ( { socialLinks.length > 0 && (
<div> <div>
<Text variant="secondary" fontSize="xs">Links</Text> <Text color="text.secondary" fontSize="xs">Links</Text>
<Grid templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(3, 1fr)' }} columnGap={ 4 } rowGap={ 3 } mt={ 3 }> <Grid templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(3, 1fr)' }} columnGap={ 4 } rowGap={ 3 } mt={ 3 }>
{ socialLinks.map((link) => <ServiceLink key={ link.field } { ...link }/>) } { socialLinks.map((link) => <ServiceLink key={ link.field } { ...link }/>) }
</Grid> </Grid>
...@@ -79,7 +79,7 @@ const Content = ({ data }: Props) => { ...@@ -79,7 +79,7 @@ const Content = ({ data }: Props) => {
) } ) }
{ priceTickersLinks.length > 0 && ( { priceTickersLinks.length > 0 && (
<div> <div>
<Text variant="secondary" fontSize="xs">Crypto markets</Text> <Text color="text.secondary" fontSize="xs">Crypto markets</Text>
<Grid templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(3, 1fr)' }} columnGap={ 4 } rowGap={ 3 } mt={ 3 }> <Grid templateColumns={{ base: 'repeat(2, 1fr)', lg: 'repeat(3, 1fr)' }} columnGap={ 4 } rowGap={ 3 } mt={ 3 }>
{ priceTickersLinks.map((link) => <ServiceLink key={ link.field } { ...link }/>) } { priceTickersLinks.map((link) => <ServiceLink key={ link.field } { ...link }/>) }
</Grid> </Grid>
......
import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { Link } from 'toolkit/chakra/link';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
...@@ -16,7 +16,7 @@ const DocsLink = ({ href }: Props) => { ...@@ -16,7 +16,7 @@ const DocsLink = ({ href }: Props) => {
alignItems="center" alignItems="center"
columnGap={ 1 } columnGap={ 1 }
> >
<IconSvg name="docs" boxSize={ 6 } color="text_secondary"/> <IconSvg name="docs" boxSize={ 6 } color="text.secondary"/>
<span>Documentation</span> <span>Documentation</span>
</Link> </Link>
); );
......
import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenVerifiedInfo } from 'types/api/token'; import type { TokenVerifiedInfo } from 'types/api/token';
import { Link } from 'toolkit/chakra/link';
import type { IconName } from 'ui/shared/IconSvg'; import type { IconName } from 'ui/shared/IconSvg';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
...@@ -23,7 +23,7 @@ const ServiceLink = ({ href, title, icon }: Props) => { ...@@ -23,7 +23,7 @@ const ServiceLink = ({ href, title, icon }: Props) => {
display="inline-flex" display="inline-flex"
alignItems="center" alignItems="center"
> >
<IconSvg name={ icon } boxSize={ 5 } mr={ 2 } color="text_secondary"/> <IconSvg name={ icon } boxSize={ 5 } mr={ 2 } color="text.secondary"/>
<span>{ title }</span> <span>{ title }</span>
</Link> </Link>
); );
......
import { Link } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import { Link } from 'toolkit/chakra/link';
import IconSvg from 'ui/shared/IconSvg'; import IconSvg from 'ui/shared/IconSvg';
interface Props { interface Props {
...@@ -19,7 +19,7 @@ const SupportLink = ({ url }: Props) => { ...@@ -19,7 +19,7 @@ const SupportLink = ({ url }: Props) => {
alignItems="center" alignItems="center"
columnGap={ 1 } columnGap={ 1 }
> >
<IconSvg name={ isEmail ? 'email' : 'link' } boxSize={ 6 } color="text_secondary"/> <IconSvg name={ isEmail ? 'email' : 'link' } boxSize={ 6 } color="text.secondary"/>
<span>{ url }</span> <span>{ url }</span>
</Link> </Link>
); );
......
...@@ -74,7 +74,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru ...@@ -74,7 +74,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru
<Box display={{ base: 'none', lg: 'block' }}> <Box display={{ base: 'none', lg: 'block' }}>
<TokenTransferTable <TokenTransferTable
data={ data?.items } data={ data?.items }
top={ pagination.isVisible ? TABS_HEIGHT : 0 } top={ TABS_HEIGHT }
showSocketInfo={ pagination.page === 1 } showSocketInfo={ pagination.page === 1 }
socketInfoAlert={ socketAlert } socketInfoAlert={ socketAlert }
socketInfoNum={ newItemsCount } socketInfoNum={ newItemsCount }
...@@ -107,11 +107,12 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru ...@@ -107,11 +107,12 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru
return ( return (
<DataListDisplay <DataListDisplay
isError={ isError || isTokenError } isError={ isError || isTokenError }
items={ data?.items } itemsNum={ data?.items.length }
emptyText="There are no token transfers." emptyText="There are no token transfers."
content={ content }
actionBar={ actionBar } actionBar={ actionBar }
/> >
{ content }
</DataListDisplay>
); );
}; };
......
...@@ -5,9 +5,9 @@ import type { TokenTransfer } from 'types/api/tokenTransfer'; ...@@ -5,9 +5,9 @@ import type { TokenTransfer } from 'types/api/tokenTransfer';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
import { Badge } from 'toolkit/chakra/badge';
import { Skeleton } from 'toolkit/chakra/skeleton';
import AddressFromTo from 'ui/shared/address/AddressFromTo'; import AddressFromTo from 'ui/shared/address/AddressFromTo';
import Skeleton from 'ui/shared/chakra/Skeleton';
import Tag from 'ui/shared/chakra/Tag';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile'; import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
...@@ -36,7 +36,7 @@ const TokenTransferListItem = ({ ...@@ -36,7 +36,7 @@ const TokenTransferListItem = ({
}) : { usd: null, valueStr: null }; }) : { usd: null, valueStr: null };
return ( return (
<ListItemMobile rowGap={ 3 } isAnimated> <ListItemMobile rowGap={ 3 }>
<Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%"> <Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%">
<TxEntity <TxEntity
isLoading={ isLoading } isLoading={ isLoading }
...@@ -48,13 +48,13 @@ const TokenTransferListItem = ({ ...@@ -48,13 +48,13 @@ const TokenTransferListItem = ({
timestamp={ timestamp } timestamp={ timestamp }
enableIncrement enableIncrement
isLoading={ isLoading } isLoading={ isLoading }
color="text_secondary" color="text.secondary"
fontWeight="400" fontWeight="400"
fontSize="sm" fontSize="sm"
display="inline-block" display="inline-block"
/> />
</Flex> </Flex>
{ method && <Tag isLoading={ isLoading }>{ method }</Tag> } { method && <Badge loading={ isLoading }>{ method }</Badge> }
<AddressFromTo <AddressFromTo
from={ from } from={ from }
to={ to } to={ to }
...@@ -65,12 +65,12 @@ const TokenTransferListItem = ({ ...@@ -65,12 +65,12 @@ const TokenTransferListItem = ({
/> />
{ valueStr && token && (token.type === 'ERC-20' || token.type === 'ERC-1155') && ( { valueStr && token && (token.type === 'ERC-20' || token.type === 'ERC-1155') && (
<Grid gap={ 2 } templateColumns={ `1fr auto auto${ usd ? ' auto' : '' }` }> <Grid gap={ 2 } templateColumns={ `1fr auto auto${ usd ? ' auto' : '' }` }>
<Skeleton isLoaded={ !isLoading } flexShrink={ 0 } fontWeight={ 500 }> <Skeleton loading={ isLoading } flexShrink={ 0 } fontWeight={ 500 }>
Value Value
</Skeleton> </Skeleton>
<Skeleton <Skeleton
isLoaded={ !isLoading } loading={ isLoading }
color="text_secondary" color="text.secondary"
wordBreak="break-all" wordBreak="break-all"
overflow="hidden" overflow="hidden"
flexGrow={ 1 } flexGrow={ 1 }
...@@ -80,8 +80,8 @@ const TokenTransferListItem = ({ ...@@ -80,8 +80,8 @@ const TokenTransferListItem = ({
{ token.symbol && <TruncatedValue isLoading={ isLoading } value={ token.symbol }/> } { token.symbol && <TruncatedValue isLoading={ isLoading } value={ token.symbol }/> }
{ usd && ( { usd && (
<Skeleton <Skeleton
isLoaded={ !isLoading } loading={ isLoading }
color="text_secondary" color="text.secondary"
wordBreak="break-all" wordBreak="break-all"
overflow="hidden" overflow="hidden"
> >
......
import { Table, Tbody, Tr, Th } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenInfo } from 'types/api/token'; import type { TokenInfo } from 'types/api/token';
...@@ -6,8 +5,8 @@ import type { TokenTransfer } from 'types/api/tokenTransfer'; ...@@ -6,8 +5,8 @@ import type { TokenTransfer } from 'types/api/tokenTransfer';
import { AddressHighlightProvider } from 'lib/contexts/addressHighlight'; import { AddressHighlightProvider } from 'lib/contexts/addressHighlight';
import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
import { TableBody, TableColumnHeader, TableHeaderSticky, TableRoot, TableRow } from 'toolkit/chakra/table';
import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice'; import * as SocketNewItemsNotice from 'ui/shared/SocketNewItemsNotice';
import { default as Thead } from 'ui/shared/TheadSticky';
import TruncatedValue from 'ui/shared/TruncatedValue'; import TruncatedValue from 'ui/shared/TruncatedValue';
import TokenTransferTableItem from 'ui/token/TokenTransfer/TokenTransferTableItem'; import TokenTransferTableItem from 'ui/token/TokenTransfer/TokenTransferTableItem';
...@@ -28,23 +27,23 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket ...@@ -28,23 +27,23 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
return ( return (
<AddressHighlightProvider> <AddressHighlightProvider>
<Table minW="950px"> <TableRoot minW="950px">
<Thead top={ top }> <TableHeaderSticky top={ top }>
<Tr> <TableRow>
<Th width="280px">Txn hash</Th> <TableColumnHeader width="280px">Txn hash</TableColumnHeader>
<Th width="200px">Method</Th> <TableColumnHeader width="200px">Method</TableColumnHeader>
<Th width={{ lg: '224px', xl: '380px' }}>From/To</Th> <TableColumnHeader width={{ lg: '224px', xl: '380px' }}>From/To</TableColumnHeader>
{ (NFT_TOKEN_TYPE_IDS.includes(tokenType)) && { (NFT_TOKEN_TYPE_IDS.includes(tokenType)) &&
<Th width={ tokenType === 'ERC-1155' || tokenType === 'ERC-404' ? '50%' : '100%' }>Token ID</Th> <TableColumnHeader width={ tokenType === 'ERC-1155' || tokenType === 'ERC-404' ? '50%' : '100%' }>Token ID</TableColumnHeader>
} }
{ (tokenType === 'ERC-20' || tokenType === 'ERC-1155' || tokenType === 'ERC-404') && ( { (tokenType === 'ERC-20' || tokenType === 'ERC-1155' || tokenType === 'ERC-404') && (
<Th width={ tokenType === 'ERC-20' ? '100%' : '50%' } isNumeric> <TableColumnHeader width={ tokenType === 'ERC-20' ? '100%' : '50%' } isNumeric>
<TruncatedValue value={ `Value ${ token?.symbol || '' }` } w="100%" verticalAlign="middle"/> <TruncatedValue value={ `Value ${ token?.symbol || '' }` } w="100%" verticalAlign="middle"/>
</Th> </TableColumnHeader>
) } ) }
</Tr> </TableRow>
</Thead> </TableHeaderSticky>
<Tbody> <TableBody>
{ showSocketInfo && ( { showSocketInfo && (
<SocketNewItemsNotice.Desktop <SocketNewItemsNotice.Desktop
url={ window.location.href } url={ window.location.href }
...@@ -62,8 +61,8 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket ...@@ -62,8 +61,8 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
isLoading={ isLoading } isLoading={ isLoading }
/> />
)) } )) }
</Tbody> </TableBody>
</Table> </TableRoot>
</AddressHighlightProvider> </AddressHighlightProvider>
); );
}; };
......
import { Tr, Td, Flex, Box } from '@chakra-ui/react'; import { Flex, Box } from '@chakra-ui/react';
import React from 'react'; import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer'; import type { TokenTransfer } from 'types/api/tokenTransfer';
import getCurrencyValue from 'lib/getCurrencyValue'; import getCurrencyValue from 'lib/getCurrencyValue';
import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes'; import { NFT_TOKEN_TYPE_IDS } from 'lib/token/tokenTypes';
import { Badge } from 'toolkit/chakra/badge';
import { Skeleton } from 'toolkit/chakra/skeleton';
import { TableCell, TableRow } from 'toolkit/chakra/table';
import AddressFromTo from 'ui/shared/address/AddressFromTo'; import AddressFromTo from 'ui/shared/address/AddressFromTo';
import Skeleton from 'ui/shared/chakra/Skeleton';
import Tag from 'ui/shared/chakra/Tag';
import NftEntity from 'ui/shared/entities/nft/NftEntity'; import NftEntity from 'ui/shared/entities/nft/NftEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity'; import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip'; import TimeAgoWithTooltip from 'ui/shared/TimeAgoWithTooltip';
...@@ -34,8 +35,8 @@ const TokenTransferTableItem = ({ ...@@ -34,8 +35,8 @@ const TokenTransferTableItem = ({
}) : { usd: null, valueStr: null }; }) : { usd: null, valueStr: null };
return ( return (
<Tr alignItems="top"> <TableRow alignItems="top">
<Td> <TableCell>
<Flex alignItems="center" py="7px"> <Flex alignItems="center" py="7px">
<TxEntity <TxEntity
hash={ txHash } hash={ txHash }
...@@ -54,15 +55,15 @@ const TokenTransferTableItem = ({ ...@@ -54,15 +55,15 @@ const TokenTransferTableItem = ({
ml="10px" ml="10px"
/> />
</Flex> </Flex>
</Td> </TableCell>
<Td> <TableCell>
{ method ? ( { method ? (
<Box my="3px"> <Box my="3px">
<Tag isLoading={ isLoading } isTruncated>{ method }</Tag> <Badge loading={ isLoading } truncated>{ method }</Badge>
</Box> </Box>
) : null } ) : null }
</Td> </TableCell>
<Td> <TableCell>
<AddressFromTo <AddressFromTo
from={ from } from={ from }
to={ to } to={ to }
...@@ -71,9 +72,9 @@ const TokenTransferTableItem = ({ ...@@ -71,9 +72,9 @@ const TokenTransferTableItem = ({
mode={{ lg: 'compact', xl: 'long' }} mode={{ lg: 'compact', xl: 'long' }}
tokenHash={ token?.address } tokenHash={ token?.address }
/> />
</Td> </TableCell>
{ (token && NFT_TOKEN_TYPE_IDS.includes(token.type)) && ( { (token && NFT_TOKEN_TYPE_IDS.includes(token.type)) && (
<Td> <TableCell>
{ total && 'token_id' in total && token && total.token_id !== null ? ( { total && 'token_id' in total && token && total.token_id !== null ? (
<NftEntity <NftEntity
hash={ token.address } hash={ token.address }
...@@ -83,23 +84,23 @@ const TokenTransferTableItem = ({ ...@@ -83,23 +84,23 @@ const TokenTransferTableItem = ({
/> />
) : '' ) : ''
} }
</Td> </TableCell>
) } ) }
{ token && (token.type === 'ERC-20' || token.type === 'ERC-1155' || token.type === 'ERC-404') && ( { token && (token.type === 'ERC-20' || token.type === 'ERC-1155' || token.type === 'ERC-404') && (
<Td isNumeric verticalAlign="top"> <TableCell isNumeric verticalAlign="top">
{ valueStr && ( { valueStr && (
<Skeleton isLoaded={ !isLoading } display="inline-block" mt="7px" wordBreak="break-all"> <Skeleton loading={ isLoading } display="inline-block" mt="7px" wordBreak="break-all">
{ valueStr } { valueStr }
</Skeleton> </Skeleton>
) } ) }
{ usd && ( { usd && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" mt="10px" wordBreak="break-all"> <Skeleton loading={ isLoading } color="text.secondary" mt="10px" wordBreak="break-all">
<span>${ usd }</span> <span>${ usd }</span>
</Skeleton> </Skeleton>
) } ) }
</Td> </TableCell>
) } ) }
</Tr> </TableRow>
); );
}; };
......
...@@ -5,8 +5,8 @@ import type { TokenVerifiedInfo as TTokenVerifiedInfo } from 'types/api/token'; ...@@ -5,8 +5,8 @@ import type { TokenVerifiedInfo as TTokenVerifiedInfo } from 'types/api/token';
import config from 'configs/app'; import config from 'configs/app';
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 LinkExternal from 'ui/shared/links/LinkExternal'; import { Skeleton } from 'toolkit/chakra/skeleton';
import TokenProjectInfo from './TokenProjectInfo'; import TokenProjectInfo from './TokenProjectInfo';
...@@ -26,9 +26,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => { ...@@ -26,9 +26,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => {
if (isPending) { if (isPending) {
return ( return (
<> <>
<Skeleton w="100px" h="30px" borderRadius="base"/> <Skeleton loading w="100px" h="30px" borderRadius="base"/>
<Skeleton w="100px" h="30px" borderRadius="base"/> <Skeleton loading w="100px" h="30px" borderRadius="base"/>
<Skeleton w="70px" h="30px" borderRadius="base"/> <Skeleton loading w="70px" h="30px" borderRadius="base"/>
</> </>
); );
} }
...@@ -41,9 +41,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => { ...@@ -41,9 +41,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => {
try { try {
const url = new URL(data.projectWebsite); const url = new URL(data.projectWebsite);
return ( return (
<LinkExternal href={ data.projectWebsite } variant="subtle" flexShrink={ 0 } fontSize="sm" lineHeight={ 5 }> <Link external href={ data.projectWebsite } variant="underlaid" flexShrink={ 0 } textStyle="sm">
{ url.host } { url.host }
</LinkExternal> </Link>
); );
} catch (error) { } catch (error) {
return null; return null;
......
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