Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
vicotor
frontend
Commits
6e4b3187
Commit
6e4b3187
authored
Feb 19, 2025
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
token page
parent
359ce166
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
197 additions
and
206 deletions
+197
-206
.env.base
configs/envs/.env.base
+17
-11
index.tsx
pages/token/[hash]/index.tsx
+2
-2
Token.tsx
ui/pages/Token.tsx
+5
-6
EntityTag.tsx
ui/shared/EntityTags/EntityTag.tsx
+1
-1
EntityTags.tsx
ui/shared/EntityTags/EntityTags.tsx
+1
-1
InfoButton.tsx
ui/shared/InfoButton.tsx
+18
-28
ResetIconButton.tsx
ui/shared/ResetIconButton.tsx
+5
-12
TokenDetails.tsx
ui/token/TokenDetails.tsx
+12
-13
TokenHolders.tsx
ui/token/TokenHolders/TokenHolders.tsx
+12
-9
TokenHoldersListItem.tsx
ui/token/TokenHolders/TokenHoldersListItem.tsx
+3
-3
TokenHoldersTable.tsx
ui/token/TokenHolders/TokenHoldersTable.tsx
+13
-14
TokenHoldersTableItem.tsx
ui/token/TokenHolders/TokenHoldersTableItem.tsx
+14
-14
TokenInventory.tsx
ui/token/TokenInventory.tsx
+4
-3
TokenInventoryItem.tsx
ui/token/TokenInventoryItem.tsx
+12
-13
TokenNftMarketplaces.tsx
ui/token/TokenNftMarketplaces.tsx
+6
-4
TokenPageTitle.tsx
ui/token/TokenPageTitle.tsx
+7
-8
Content.tsx
ui/token/TokenProjectInfo/Content.tsx
+3
-3
DocsLink.tsx
ui/token/TokenProjectInfo/DocsLink.tsx
+2
-2
ServiceLink.tsx
ui/token/TokenProjectInfo/ServiceLink.tsx
+2
-2
SupportLink.tsx
ui/token/TokenProjectInfo/SupportLink.tsx
+2
-2
TokenTransfer.tsx
ui/token/TokenTransfer/TokenTransfer.tsx
+5
-4
TokenTransferListItem.tsx
ui/token/TokenTransfer/TokenTransferListItem.tsx
+10
-10
TokenTransferTable.tsx
ui/token/TokenTransfer/TokenTransferTable.tsx
+15
-16
TokenTransferTableItem.tsx
ui/token/TokenTransfer/TokenTransferTableItem.tsx
+19
-18
TokenVerifiedInfo.tsx
ui/token/TokenVerifiedInfo.tsx
+7
-7
No files found.
configs/envs/.env.base
View file @
6e4b3187
...
...
@@ -10,37 +10,41 @@ NEXT_PUBLIC_APP_ENV=development
NEXT_PUBLIC_API_WEBSOCKET_PROTOCOL=ws
# 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_API_BASE_PATH=/
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_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_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_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_HAS_CONTRACT_AUDIT_REPORTS=true
NEXT_PUBLIC_HAS_USER_OPS=true
NEXT_PUBLIC_HIDE_INDEXING_ALERT_INT_TXS=true
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_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_MARKETPLACE_BANNER_LINK_URL=https://base.blockscout.com/apps/peanut-protocol
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_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_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_SUBMIT_FORM=https://airtable.com/appiy5yijZpMMSKjT/shr6uMGPKjj1DK7NL
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_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.sv
g'}]
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.pn
g'}]
NEXT_PUBLIC_NAME_SERVICE_API_HOST=https://bens.services.blockscout.com
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/
app
s']
NEXT_PUBLIC_NAVIGATION_HIGHLIGHTED_ROUTES=['/
pool
s']
NEXT_PUBLIC_NETWORK_CURRENCY_DECIMALS=18
NEXT_PUBLIC_NETWORK_CURRENCY_NAME=Ether
NEXT_PUBLIC_NETWORK_CURRENCY_SYMBOL=ETH
...
...
@@ -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_TYPE=optimistic
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_VIEWS_ADDRESS_IDENTICON_TYPE=gradient_avatar
NEXT_PUBLIC_VIEWS_CONTRACT_SOLIDITYSCAN_ENABLED=true
NEXT_PUBLIC_VISUALIZE_API_HOST=https://visualizer.services.blockscout.com
\ No newline at end of file
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'}]
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
pages/token/[hash]/index.tsx
View file @
6e4b3187
...
...
@@ -10,14 +10,14 @@ import fetchApi from 'nextjs/utils/fetchApi';
import
config
from
'
configs/app
'
;
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
Page
:
NextPage
<
Props
<
typeof
pathname
>>
=
(
props
:
Props
<
typeof
pathname
>
)
=>
{
return
(
<
PageNextJs
pathname=
{
pathname
}
query=
{
props
.
query
}
apiData=
{
props
.
apiData
}
>
{
/* <Token/> */
}
<
Token
/>
</
PageNextJs
>
);
};
...
...
ui/pages/Token.tsx
View file @
6e4b3187
...
...
@@ -4,9 +4,9 @@ import { useRouter } from 'next/router';
import
React
,
{
useEffect
}
from
'
react
'
;
import
type
{
SocketMessage
}
from
'
lib/socket/types
'
;
import
type
{
TabItemRegular
}
from
'
toolkit/components/AdaptiveTabs/types
'
;
import
type
{
TokenInfo
}
from
'
types/api/token
'
;
import
type
{
PaginationParams
}
from
'
ui/shared/pagination/types
'
;
import
type
{
RoutedTab
}
from
'
ui/shared/Tabs/types
'
;
import
config
from
'
configs/app
'
;
import
useApiQuery
,
{
getResourceKey
}
from
'
lib/api/useApiQuery
'
;
...
...
@@ -20,6 +20,7 @@ import * as addressStubs from 'stubs/address';
import
*
as
tokenStubs
from
'
stubs/token
'
;
import
{
getTokenHoldersStub
}
from
'
stubs/token
'
;
import
{
generateListStub
}
from
'
stubs/utils
'
;
import
RoutedTabs
from
'
toolkit/components/RoutedTabs/RoutedTabs
'
;
import
AddressContract
from
'
ui/address/AddressContract
'
;
import
AddressCsvExportLink
from
'
ui/address/AddressCsvExportLink
'
;
import
useContractTabs
from
'
ui/address/contract/useContractTabs
'
;
...
...
@@ -28,7 +29,6 @@ import TextAd from 'ui/shared/ad/TextAd';
import
IconSvg
from
'
ui/shared/IconSvg
'
;
import
Pagination
from
'
ui/shared/pagination/Pagination
'
;
import
useQueryWithPages
from
'
ui/shared/pagination/useQueryWithPages
'
;
import
RoutedTabs
from
'
ui/shared/Tabs/RoutedTabs
'
;
import
TokenDetails
from
'
ui/token/TokenDetails
'
;
import
TokenHolders
from
'
ui/token/TokenHolders/TokenHolders
'
;
import
TokenInventory
from
'
ui/token/TokenInventory
'
;
...
...
@@ -161,7 +161,7 @@ const TokenPageContent = () => {
const isLoading = tokenQuery.isPlaceholderData || addressQuery.isPlaceholderData;
const contractTabs = useContractTabs(addressQuery.data, addressQuery.isPlaceholderData);
const tabs: Array<
RoutedTab
> = [
const tabs: Array<
TabItemRegular
> = [
hasInventoryTab ? {
id: 'inventory',
title: 'Inventory',
...
...
@@ -212,7 +212,7 @@ const TokenPageContent = () => {
pagination = inventoryQuery.pagination;
}
const tabListProps = React.useCallback((
{ isSticky, activeTabIndex }: { isSticky: boolean; activeTabIndex: number }
) => {
const tabListProps = React.useCallback(() => {
if (isMobile) {
return { mt: 8 };
}
...
...
@@ -221,7 +221,6 @@ const TokenPageContent = () => {
pt: 6,
pb: 6,
marginBottom: 0,
boxShadow: activeTabIndex === 2 && isSticky ? 'action_bar' : 'none',
};
}, [ isMobile ]);
...
...
@@ -257,7 +256,7 @@ const TokenPageContent = () => {
<RoutedTabs
tabs={ tabs }
tabL
istProps={ tabListProps }
l
istProps={ tabListProps }
rightSlot={ tabsRightSlot }
rightSlotProps={ TABS_RIGHT_SLOT_PROPS }
stickyEnabled={ !isMobile }
...
...
ui/shared/EntityTags/EntityTag.tsx
View file @
6e4b3187
...
...
@@ -82,6 +82,7 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => {
onClick=
{
handleLinkClick
}
noIcon
cursor=
{
hasLink
?
'
pointer
'
:
'
default
'
}
{
...
rest
}
>
<
Tag
bg=
{
data
.
meta
?.
bgColor
}
...
...
@@ -92,7 +93,6 @@ const EntityTag = ({ data, isLoading, noLink, ...rest }: Props) => {
endElementProps=
{
linkParams
?.
type
===
'
external
'
?
{
ml
:
-
1
}
:
undefined
}
_hover=
{
hasLink
?
{
opacity
:
0.76
}
:
undefined
}
variant=
{
hasLink
?
'
clickable
'
:
'
subtle
'
}
{
...
rest
}
>
{
prefix
}{
name
}
</
Tag
>
...
...
ui/shared/EntityTags/EntityTags.tsx
View file @
6e4b3187
...
...
@@ -45,7 +45,7 @@ const EntityTags = ({ tags, className, isLoading }: Props) => {
+
{
tags
.
length
-
visibleNum
}
</
Badge
>
</
PopoverTrigger
>
<
PopoverContent
maxW=
"300px"
>
<
PopoverContent
maxW=
"300px"
w=
"fit-content"
>
<
PopoverBody
>
<
Flex
columnGap=
{
2
}
rowGap=
{
2
}
flexWrap=
"wrap"
>
{
tags
.
slice
(
visibleNum
).
map
((
tag
)
=>
<
EntityTag
key=
{
tag
.
slug
}
data=
{
tag
}
/>)
}
...
...
ui/shared/InfoButton.tsx
View file @
6e4b3187
import
{
PopoverTrigger
,
PopoverContent
,
PopoverBody
,
Modal
,
ModalContent
,
ModalCloseButton
,
useDisclosure
,
Button
,
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
useIsMobile
from
'
lib/hooks/useIsMobile
'
;
import
Popover
from
'
ui/shared/chakra/Popover
'
;
import
IconSvg
from
'
./IconSvg
'
;
import
{
Button
}
from
'
toolkit/chakra/button
'
;
import
{
DialogRoot
,
DialogContent
,
DialogTrigger
,
DialogHeader
}
from
'
toolkit/chakra/dialog
'
;
import
{
PopoverBody
,
PopoverContent
,
PopoverRoot
,
PopoverTrigger
}
from
'
toolkit/chakra/popover
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
interface
Props
{
children
:
React
.
ReactNode
;
...
...
@@ -17,21 +12,16 @@ interface Props {
const
InfoButton
=
({
children
}:
Props
)
=>
{
const
isMobile
=
useIsMobile
();
const
{
isOpen
,
onToggle
,
onClose
}
=
useDisclosure
();
const
triggerButton
=
(
<
Button
size=
"sm"
variant=
"outline"
colorScheme=
"gray"
onClick=
{
onToggle
}
isActive=
{
isOpen
}
variant=
"dropdown"
gap=
{
0
}
aria
-
label=
"Show info"
fontWeight=
{
500
}
lineHeight=
{
6
}
pl=
{
1
}
pr=
{
isMobile
?
1
:
2
}
h=
"32px"
>
<
IconSvg
name=
"info"
boxSize=
{
6
}
mr=
{
isMobile
?
0
:
1
}
/>
{
!
isMobile
&&
<
span
>
Info
</
span
>
}
...
...
@@ -40,29 +30,29 @@ const InfoButton = ({ children }: Props) => {
if
(
isMobile
)
{
return
(
<>
{
triggerButton
}
<
Modal
isOpen=
{
isOpen
}
onClose=
{
onClose
}
size=
"full"
>
<
ModalContent
>
<
ModalCloseButton
/
>
{
children
}
</
ModalContent
>
</
Modal
>
</>
<
DialogRoot
size=
"full"
>
<
DialogTrigger
>
{
triggerButton
}
</
DialogTrigger
>
<
DialogContent
>
<
DialogHeader
/>
{
children
}
</
DialogContent
>
</
DialogRoot
>
);
}
return
(
<
Popover
isOpen=
{
isOpen
}
onClose=
{
onClose
}
placement=
"bottom-start"
isLazy
>
<
Popover
Root
>
<
PopoverTrigger
>
{
triggerButton
}
</
PopoverTrigger
>
<
PopoverContent
w=
"500px"
>
<
PopoverBody
px=
{
6
}
py=
{
5
}
>
<
PopoverBody
>
{
children
}
</
PopoverBody
>
</
PopoverContent
>
</
Popover
>
</
Popover
Root
>
);
};
...
...
ui/shared/ResetIconButton.tsx
View file @
6e4b3187
import
{
Tooltip
,
Flex
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
IconButton
}
from
'
toolkit/chakra/icon-button
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
type
Props
=
{
...
...
@@ -8,22 +9,14 @@ type Props = {
};
const
ResetIconButton
=
({
onClick
}:
Props
)
=>
{
const
resetTokenIconColor
=
useColorModeValue
(
'
blue.600
'
,
'
blue.300
'
);
const
resetTokenIconHoverColor
=
useColorModeValue
(
'
blue.400
'
,
'
blue.200
'
);
return
(
<
Tooltip
label
=
"Reset filter"
>
<
Flex
>
<
Tooltip
content
=
"Reset filter"
>
<
IconButton
ml=
{
1
}
variant=
"link"
onClick=
{
onClick
}
>
<
IconSvg
name=
"cross"
boxSize=
{
5
}
ml=
{
1
}
color=
{
resetTokenIconColor
}
cursor=
"pointer"
_hover=
{
{
color
:
resetTokenIconHoverColor
}
}
onClick=
{
onClick
}
/>
</
Flex
>
</
IconButton
>
</
Tooltip
>
);
};
...
...
ui/token/TokenDetails.tsx
View file @
6e4b3187
import
{
Box
,
Grid
,
Link
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Grid
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
{
useRouter
}
from
'
next/router
'
;
...
...
@@ -14,10 +14,11 @@ import throwOnResourceLoadError from 'lib/errors/throwOnResourceLoadError';
import
getCurrencyValue
from
'
lib/getCurrencyValue
'
;
import
useIsMounted
from
'
lib/hooks/useIsMounted
'
;
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
AppActionButton
from
'
ui/shared/AppActionButton/AppActionButton
'
;
import
useAppActionData
from
'
ui/shared/AppActionButton/useAppActionData
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
*
as
DetailedInfo
from
'
ui/shared/DetailedInfo/DetailedInfo
'
;
import
DetailedInfoSponsoredItem
from
'
ui/shared/DetailedInfo/DetailedInfoSponsoredItem
'
;
import
TruncatedValue
from
'
ui/shared/TruncatedValue
'
;
...
...
@@ -65,11 +66,9 @@ const TokenDetails = ({ tokenQuery }: Props) => {
const
tab
:
TokenTabs
=
item
===
'
token_holders_count
'
?
'
holders
'
:
'
token_transfers
'
;
return
(
<
Skeleton
isLoaded=
{
!
tokenCountersQuery
.
isPlaceholderData
}
>
<
Link
onClick=
{
changeUrlAndScroll
(
tab
)
}
>
{
Number
(
itemValue
).
toLocaleString
()
}
</
Link
>
</
Skeleton
>
<
Link
onClick=
{
changeUrlAndScroll
(
tab
)
}
loading=
{
tokenCountersQuery
.
isPlaceholderData
}
>
{
Number
(
itemValue
).
toLocaleString
()
}
</
Link
>
);
},
[
tokenCountersQuery
.
data
,
tokenCountersQuery
.
isPlaceholderData
,
changeUrlAndScroll
]);
...
...
@@ -112,7 +111,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Price
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
tokenQuery
.
isPlaceholderData
}
display=
"inline-block"
>
<
Skeleton
loading=
{
tokenQuery
.
isPlaceholderData
}
display=
"inline-block"
>
<
span
>
{
`$${ Number(exchangeRate).toLocaleString(undefined, { minimumSignificantDigits: 4 }) }`
}
</
span
>
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -128,7 +127,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Fully diluted market cap
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
tokenQuery
.
isPlaceholderData
}
display=
"inline-block"
>
<
Skeleton
loading=
{
tokenQuery
.
isPlaceholderData
}
display=
"inline-block"
>
<
span
>
{
`$${ BigNumber(marketCap).toFormat() }`
}
</
span
>
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -146,7 +145,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
wordBreak=
"break-word"
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
}
/>
<
Box
flexShrink=
{
0
}
>
</
Box
>
<
TruncatedValue
value=
{
symbol
||
''
}
/>
...
...
@@ -160,7 +159,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Holders
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
tokenCountersQuery
.
isPlaceholderData
}
>
<
Skeleton
loading=
{
tokenCountersQuery
.
isPlaceholderData
}
>
{
countersItem
(
'
token_holders_count
'
)
}
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -172,7 +171,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Transfers
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
tokenCountersQuery
.
isPlaceholderData
}
>
<
Skeleton
loading=
{
tokenCountersQuery
.
isPlaceholderData
}
>
{
countersItem
(
'
transfers_count
'
)
}
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
@@ -186,7 +185,7 @@ const TokenDetails = ({ tokenQuery }: Props) => {
Decimals
</
DetailedInfo
.
ItemLabel
>
<
DetailedInfo
.
ItemValue
>
<
Skeleton
isLoaded=
{
!
tokenQuery
.
isPlaceholderData
}
minW=
{
6
}
>
<
Skeleton
loading=
{
tokenQuery
.
isPlaceholderData
}
minW=
{
6
}
>
{
decimals
}
</
Skeleton
>
</
DetailedInfo
.
ItemValue
>
...
...
ui/token/TokenHolders/TokenHolders.tsx
View file @
6e4b3187
...
...
@@ -37,11 +37,13 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
const
actionBar
=
isMobile
&&
holdersQuery
.
pagination
.
isVisible
&&
(
<
ActionBar
mt=
{
-
6
}
>
<
AddressCsvExportLink
address=
{
token
?.
address
}
params=
{
{
type
:
'
holders
'
}
}
isLoading=
{
holdersQuery
.
pagination
.
isLoading
}
/>
{
token
&&
(
<
AddressCsvExportLink
address=
{
token
.
address
}
params=
{
{
type
:
'
holders
'
}
}
isLoading=
{
holdersQuery
.
pagination
.
isLoading
}
/>
)
}
<
Pagination
ml=
"auto"
{
...
holdersQuery
.
pagination
}
/>
</
ActionBar
>
);
...
...
@@ -54,7 +56,7 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
<
TokenHoldersTable
data=
{
items
}
token=
{
token
}
top=
{
holdersQuery
.
pagination
.
isVisible
?
TABS_HEIGHT
:
0
}
top=
{
TABS_HEIGHT
}
isLoading=
{
holdersQuery
.
isPlaceholderData
}
/>
</
Box
>
...
...
@@ -71,11 +73,12 @@ const TokenHoldersContent = ({ holdersQuery, token, shouldRender = true }: Props
return
(
<
DataListDisplay
isError=
{
holdersQuery
.
isError
}
items
=
{
holdersQuery
.
data
?.
items
}
items
Num=
{
holdersQuery
.
data
?.
items
.
length
}
emptyText=
"There are no holders for this token."
content=
{
content
}
actionBar=
{
actionBar
}
/>
>
{
content
}
</
DataListDisplay
>
);
};
...
...
ui/token/TokenHolders/TokenHoldersListItem.tsx
View file @
6e4b3187
...
...
@@ -3,7 +3,7 @@ import React from 'react';
import
type
{
TokenHolder
,
TokenInfo
}
from
'
types/api/token
'
;
import
Skeleton
from
'
ui/shared/chakra/S
keleton
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/s
keleton
'
;
import
AddressEntity
from
'
ui/shared/entities/address/AddressEntity
'
;
import
ListItemMobileGrid
from
'
ui/shared/ListItemMobile/ListItemMobileGrid
'
;
import
Utilization
from
'
ui/shared/Utilization/Utilization
'
;
...
...
@@ -33,7 +33,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => {
<>
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
ID#
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
<
Skeleton
loading=
{
isLoading
}
display=
"inline-block"
>
{
holder
.
token_id
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
...
...
@@ -42,7 +42,7 @@ const TokenHoldersListItem = ({ holder, token, isLoading }: Props) => {
<
ListItemMobileGrid
.
Label
isLoading=
{
isLoading
}
>
Quantity
</
ListItemMobileGrid
.
Label
>
<
ListItemMobileGrid
.
Value
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
<
Skeleton
loading=
{
isLoading
}
display=
"inline-block"
>
{
quantity
}
</
Skeleton
>
</
ListItemMobileGrid
.
Value
>
...
...
ui/token/TokenHolders/TokenHoldersTable.tsx
View file @
6e4b3187
import
{
Table
,
Tbody
,
Tr
,
Th
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
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
'
;
interface
Props
{
...
...
@@ -15,21 +14,21 @@ interface Props {
const
TokenHoldersTable
=
({
data
,
token
,
top
,
isLoading
}:
Props
)
=>
{
return
(
<
Table
l
ayout=
"auto"
>
<
T
head
top=
{
top
}
>
<
T
r
>
<
T
h
>
Holder
</
Th
>
{
(
token
.
type
===
'
ERC-1155
'
||
token
.
type
===
'
ERC-404
'
)
&&
<
T
h
>
ID#
</
Th
>
}
<
T
h
isNumeric
>
Quantity
</
Th
>
{
token
.
total_supply
&&
token
.
type
!==
'
ERC-404
'
&&
<
T
h
isNumeric
width=
"175px"
>
Percentage
</
Th
>
}
</
T
r
>
</
T
head
>
<
T
b
ody
>
<
Table
Root
tableL
ayout=
"auto"
>
<
T
ableHeaderSticky
top=
{
top
}
>
<
T
ableRow
>
<
T
ableColumnHeader
>
Holder
</
TableColumnHeader
>
{
(
token
.
type
===
'
ERC-1155
'
||
token
.
type
===
'
ERC-404
'
)
&&
<
T
ableColumnHeader
>
ID#
</
TableColumnHeader
>
}
<
T
ableColumnHeader
isNumeric
>
Quantity
</
TableColumnHeader
>
{
token
.
total_supply
&&
token
.
type
!==
'
ERC-404
'
&&
<
T
ableColumnHeader
isNumeric
width=
"175px"
>
Percentage
</
TableColumnHeader
>
}
</
T
ableRow
>
</
T
ableHeaderSticky
>
<
T
ableB
ody
>
{
data
.
map
((
item
,
index
)
=>
(
<
TokenHoldersTableItem
key=
{
item
.
address
.
hash
+
(
isLoading
?
index
:
''
)
}
holder=
{
item
}
token=
{
token
}
isLoading=
{
isLoading
}
/>
))
}
</
T
b
ody
>
</
Table
>
</
T
ableB
ody
>
</
Table
Root
>
);
};
...
...
ui/token/TokenHolders/TokenHoldersTableItem.tsx
View file @
6e4b3187
import
{
Tr
,
Td
}
from
'
@chakra-ui/react
'
;
import
BigNumber
from
'
bignumber.js
'
;
import
React
from
'
react
'
;
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
Utilization
from
'
ui/shared/Utilization/Utilization
'
;
...
...
@@ -18,38 +18,38 @@ const TokenTransferTableItem = ({ holder, token, isLoading }: Props) => {
const
quantity
=
BigNumber
(
holder
.
value
).
div
(
BigNumber
(
10
**
Number
(
token
.
decimals
))).
toFormat
();
return
(
<
T
r
>
<
T
d
verticalAlign=
"middle"
>
<
T
ableRow
>
<
T
ableCell
verticalAlign=
"middle"
>
<
AddressEntity
address=
{
holder
.
address
}
isLoading=
{
isLoading
}
flexGrow=
{
1
}
fontWeight=
"700"
/>
</
T
d
>
</
T
ableCell
>
{
(
token
.
type
===
'
ERC-1155
'
||
token
.
type
===
'
ERC-404
'
)
&&
'
token_id
'
in
holder
&&
(
<
T
d
verticalAlign=
"middle"
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
>
<
T
ableCell
verticalAlign=
"middle"
>
<
Skeleton
loading=
{
isLoading
}
display=
"inline-block"
>
{
'
token_id
'
in
holder
&&
holder
.
token_id
}
</
Skeleton
>
</
T
d
>
</
T
ableCell
>
)
}
<
T
d
verticalAlign=
"middle"
isNumeric
>
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
wordBreak=
"break-word"
>
<
T
ableCell
verticalAlign=
"middle"
isNumeric
>
<
Skeleton
loading=
{
isLoading
}
display=
"inline-block"
wordBreak=
"break-word"
>
{
quantity
}
</
Skeleton
>
</
T
d
>
</
T
ableCell
>
{
token
.
total_supply
&&
token
.
type
!==
'
ERC-404
'
&&
(
<
T
d
verticalAlign=
"middle"
isNumeric
>
<
T
ableCell
verticalAlign=
"middle"
isNumeric
>
<
Utilization
value=
{
BigNumber
(
holder
.
value
).
div
(
BigNumber
(
token
.
total_supply
)).
dp
(
4
).
toNumber
()
}
colorScheme=
"green"
display=
"inline-flex"
isLoading=
{
isLoading
}
/>
</
T
d
>
</
T
ableCell
>
)
}
</
T
r
>
</
T
ableRow
>
);
};
...
...
ui/token/TokenInventory.tsx
View file @
6e4b3187
...
...
@@ -88,15 +88,16 @@ const TokenInventory = ({ inventoryQuery, tokenQuery, ownerFilter, shouldRender
return
(
<
DataListDisplay
isError=
{
inventoryQuery
.
isError
}
items
=
{
items
}
items
Num=
{
items
?.
length
}
emptyText=
"There are no tokens."
filterProps=
{
{
hasActiveFilters
:
Boolean
(
ownerFilter
),
emptyFilteredText
:
'
No tokens found for the selected owner.
'
,
}
}
content=
{
content
}
actionBar=
{
actionBar
}
/>
>
{
content
}
</
DataListDisplay
>
);
};
...
...
ui/token/TokenInventoryItem.tsx
View file @
6e4b3187
import
{
Box
,
Flex
,
Text
,
Link
,
useColorModeValue
}
from
'
@chakra-ui/react
'
;
import
{
Box
,
Flex
,
Text
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
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
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
LinkInternal
from
'
ui/shared/links/LinkInternal
'
;
import
NftMedia
from
'
ui/shared/nft/NftMedia
'
;
import
TruncatedTextTooltip
from
'
ui/shared/TruncatedTextTooltip
'
;
...
...
@@ -33,38 +33,37 @@ const TokenInventoryItem = ({ item, token, isLoading }: Props) => {
<
Box
w=
{
{
base
:
'
100%
'
,
lg
:
'
210px
'
}
}
border=
"1px solid"
borderColor=
{
useColorModeValue
(
'
blackAlpha.100
'
,
'
whiteAlpha.200
'
)
}
borderColor=
{
{
_light
:
'
blackAlpha.100
'
,
_dark
:
'
whiteAlpha.200
'
}
}
borderRadius=
"12px"
p=
"10px"
fontSiz
e=
"sm"
textStyl
e=
"sm"
fontWeight=
{
500
}
lineHeight=
"20px"
>
<
Link
href=
{
isLoading
?
undefined
:
url
}
>
<
Link
href=
{
isLoading
?
undefined
:
url
}
display=
"inline"
>
{
mediaElement
}
</
Link
>
{
item
.
id
&&
(
<
Flex
mb=
{
2
}
ml=
{
1
}
>
<
Text
whiteSpace=
"pre"
variant=
"
secondary"
>
ID#
</
Text
>
<
Text
whiteSpace=
"pre"
color=
"text.
secondary"
>
ID#
</
Text
>
<
TruncatedTextTooltip
label=
{
item
.
id
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
overflow=
"hidden"
>
<
Link
Internal
<
Skeleton
loading=
{
isLoading
}
overflow=
"hidden"
>
<
Link
overflow=
"hidden"
textOverflow=
"ellipsis"
whiteSpace=
"nowrap"
display=
"block"
isL
oading=
{
isLoading
}
l
oading=
{
isLoading
}
href=
{
url
}
>
{
item
.
id
}
</
Link
Internal
>
</
Link
>
</
Skeleton
>
</
TruncatedTextTooltip
>
</
Flex
>
)
}
{
item
.
owner
&&
(
<
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
address=
{
item
.
owner
}
isLoading=
{
isLoading
}
...
...
ui/token/TokenNftMarketplaces.tsx
View file @
6e4b3187
import
{
Image
,
Link
,
Tooltip
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
AddressMetadataTagFormatted
}
from
'
types/client/addressMetadata
'
;
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
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
*
as
DetailedInfo
from
'
ui/shared/DetailedInfo/DetailedInfo
'
;
import
TextSeparator
from
'
ui/shared/TextSeparator
'
;
...
...
@@ -33,14 +35,14 @@ const TokenNftMarketplaces = ({ hash, id, isLoading, appActionData, source }: Pr
<
DetailedInfo
.
ItemValue
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
)
=>
{
const
hrefTemplate
=
id
?
item
.
instance_url
:
item
.
collection_url
;
const
href
=
hrefTemplate
.
replace
(
'
{id}
'
,
id
||
''
).
replace
(
'
{hash}
'
,
hash
||
''
);
return
(
<
Tooltip
label
=
{
`View on ${ item.name }`
}
key=
{
item
.
name
}
>
<
Tooltip
content
=
{
`View on ${ item.name }`
}
key=
{
item
.
name
}
>
<
Link
href=
{
href
}
target=
"_blank"
>
<
Image
src=
{
item
.
logo_url
}
...
...
ui/token/TokenPageTitle.tsx
View file @
6e4b3187
import
{
Box
,
Flex
,
Tooltip
,
useToken
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
useToken
}
from
'
@chakra-ui/react
'
;
import
type
{
UseQueryResult
}
from
'
@tanstack/react-query
'
;
import
React
from
'
react
'
;
...
...
@@ -12,6 +12,7 @@ import type { ResourceError } from 'lib/api/resources';
import
useApiQuery
from
'
lib/api/useApiQuery
'
;
import
{
useAppContext
}
from
'
lib/contexts/app
'
;
import
{
getTokenTypeName
}
from
'
lib/token/tokenTypes
'
;
import
{
Tooltip
}
from
'
toolkit/chakra/tooltip
'
;
import
AddressMetadataAlert
from
'
ui/address/details/AddressMetadataAlert
'
;
import
AddressQrCode
from
'
ui/address/details/AddressQrCode
'
;
import
AccountActionsMenu
from
'
ui/shared/AccountActionsMenu/AccountActionsMenu
'
;
...
...
@@ -66,8 +67,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
};
},
[
appProps
.
referrer
]);
const
bridgedTokenTagBgColor
=
useToken
(
'
colors
'
,
'
blue.500
'
);
const
bridgedTokenTagTextColor
=
useToken
(
'
colors
'
,
'
white
'
);
const
[
bridgedTokenTagBgColor
]
=
useToken
(
'
colors
'
,
'
blue.500
'
);
const
[
bridgedTokenTagTextColor
]
=
useToken
(
'
colors
'
,
'
white
'
);
const
tags
:
Array
<
EntityTag
>
=
React
.
useMemo
(()
=>
{
return
[
...
...
@@ -105,10 +106,8 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
const
contentAfter
=
(
<>
{
verifiedInfoQuery
.
data
?.
tokenAddress
&&
(
<
Tooltip
label=
{
`Information on this token has been verified by ${ config.chain.name }`
}
>
<
Box
boxSize=
{
6
}
>
<
IconSvg
name=
"certified"
color=
"green.500"
boxSize=
{
6
}
cursor=
"pointer"
/>
</
Box
>
<
Tooltip
content=
{
`Information on this token has been verified by ${ config.chain.name }`
}
>
<
IconSvg
name=
"certified"
color=
"green.500"
boxSize=
{
6
}
cursor=
"pointer"
/>
</
Tooltip
>
)
}
<
EntityTags
...
...
@@ -131,7 +130,7 @@ const TokenPageTitle = ({ tokenQuery, addressQuery, hash }: Props) => {
/>
)
}
{
!
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
}
/>
<
Flex
ml=
{
{
base
:
0
,
lg
:
'
auto
'
}
}
columnGap=
{
2
}
flexGrow=
{
{
base
:
1
,
lg
:
0
}
}
>
<
TokenVerifiedInfo
verifiedInfoQuery=
{
verifiedInfoQuery
}
/>
...
...
ui/token/TokenProjectInfo/Content.tsx
View file @
6e4b3187
...
...
@@ -59,7 +59,7 @@ const Content = ({ data }: Props) => {
<
Flex
fontSize=
"sm"
flexDir=
"column"
rowGap=
{
5
}
>
{
(
description
||
docs
||
support
)
&&
(
<
div
>
<
Text
variant=
"
secondary"
fontSize=
"xs"
>
Description and support info
</
Text
>
<
Text
color=
"text.
secondary"
fontSize=
"xs"
>
Description and support info
</
Text
>
{
description
}
{
(
docs
||
support
)
&&
(
<
Flex
alignItems=
"center"
flexWrap=
"wrap"
columnGap=
{
6
}
mt=
{
3
}
>
...
...
@@ -71,7 +71,7 @@ const Content = ({ data }: Props) => {
)
}
{
socialLinks
.
length
>
0
&&
(
<
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
}
>
{
socialLinks
.
map
((
link
)
=>
<
ServiceLink
key=
{
link
.
field
}
{
...
link
}
/>)
}
</
Grid
>
...
...
@@ -79,7 +79,7 @@ const Content = ({ data }: Props) => {
)
}
{
priceTickersLinks
.
length
>
0
&&
(
<
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
}
>
{
priceTickersLinks
.
map
((
link
)
=>
<
ServiceLink
key=
{
link
.
field
}
{
...
link
}
/>)
}
</
Grid
>
...
...
ui/token/TokenProjectInfo/DocsLink.tsx
View file @
6e4b3187
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
interface
Props
{
...
...
@@ -16,7 +16,7 @@ const DocsLink = ({ href }: Props) => {
alignItems=
"center"
columnGap=
{
1
}
>
<
IconSvg
name=
"docs"
boxSize=
{
6
}
color=
"text
_
secondary"
/>
<
IconSvg
name=
"docs"
boxSize=
{
6
}
color=
"text
.
secondary"
/>
<
span
>
Documentation
</
span
>
</
Link
>
);
...
...
ui/token/TokenProjectInfo/ServiceLink.tsx
View file @
6e4b3187
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokenVerifiedInfo
}
from
'
types/api/token
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
type
{
IconName
}
from
'
ui/shared/IconSvg
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
...
...
@@ -23,7 +23,7 @@ const ServiceLink = ({ href, title, icon }: Props) => {
display=
"inline-flex"
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
>
</
Link
>
);
...
...
ui/token/TokenProjectInfo/SupportLink.tsx
View file @
6e4b3187
import
{
Link
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
IconSvg
from
'
ui/shared/IconSvg
'
;
interface
Props
{
...
...
@@ -19,7 +19,7 @@ const SupportLink = ({ url }: Props) => {
alignItems=
"center"
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
>
</
Link
>
);
...
...
ui/token/TokenTransfer/TokenTransfer.tsx
View file @
6e4b3187
...
...
@@ -74,7 +74,7 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru
<Box display={{ base: 'none', lg: 'block' }}>
<TokenTransferTable
data={ data?.items }
top={
pagination.isVisible ? TABS_HEIGHT : 0
}
top={
TABS_HEIGHT
}
showSocketInfo={ pagination.page === 1 }
socketInfoAlert={ socketAlert }
socketInfoNum={ newItemsCount }
...
...
@@ -107,11 +107,12 @@ const TokenTransfer = ({ transfersQuery, tokenId, tokenQuery, shouldRender = tru
return (
<DataListDisplay
isError={ isError || isTokenError }
items
={ data?.items
}
items
Num={ data?.items.length
}
emptyText="There are no token transfers."
content={ content }
actionBar={ actionBar }
/>
>
{ content }
</DataListDisplay>
);
};
...
...
ui/token/TokenTransfer/TokenTransferListItem.tsx
View file @
6e4b3187
...
...
@@ -5,9 +5,9 @@ import type { TokenTransfer } from 'types/api/tokenTransfer';
import
getCurrencyValue
from
'
lib/getCurrencyValue
'
;
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
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
import
NftEntity
from
'
ui/shared/entities/nft/NftEntity
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
ListItemMobile
from
'
ui/shared/ListItemMobile/ListItemMobile
'
;
...
...
@@ -36,7 +36,7 @@ const TokenTransferListItem = ({
})
:
{
usd
:
null
,
valueStr
:
null
};
return
(
<
ListItemMobile
rowGap=
{
3
}
isAnimated
>
<
ListItemMobile
rowGap=
{
3
}
>
<
Flex
justifyContent=
"space-between"
alignItems=
"center"
lineHeight=
"24px"
width=
"100%"
>
<
TxEntity
isLoading=
{
isLoading
}
...
...
@@ -48,13 +48,13 @@ const TokenTransferListItem = ({
timestamp=
{
timestamp
}
enableIncrement
isLoading=
{
isLoading
}
color=
"text
_
secondary"
color=
"text
.
secondary"
fontWeight=
"400"
fontSize=
"sm"
display=
"inline-block"
/>
</
Flex
>
{
method
&&
<
Tag
isLoading=
{
isLoading
}
>
{
method
}
</
Tag
>
}
{
method
&&
<
Badge
loading=
{
isLoading
}
>
{
method
}
</
Badge
>
}
<
AddressFromTo
from=
{
from
}
to=
{
to
}
...
...
@@ -65,12 +65,12 @@ const TokenTransferListItem = ({
/>
{
valueStr
&&
token
&&
(
token
.
type
===
'
ERC-20
'
||
token
.
type
===
'
ERC-1155
'
)
&&
(
<
Grid
gap=
{
2
}
templateColumns=
{
`1fr auto auto${ usd ? ' auto' : '' }`
}
>
<
Skeleton
isLoaded=
{
!
isLoading
}
flexShrink=
{
0
}
fontWeight=
{
500
}
>
<
Skeleton
loading=
{
isLoading
}
flexShrink=
{
0
}
fontWeight=
{
500
}
>
Value
</
Skeleton
>
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text
_
secondary"
loading=
{
isLoading
}
color=
"text
.
secondary"
wordBreak=
"break-all"
overflow=
"hidden"
flexGrow=
{
1
}
...
...
@@ -80,8 +80,8 @@ const TokenTransferListItem = ({
{
token
.
symbol
&&
<
TruncatedValue
isLoading=
{
isLoading
}
value=
{
token
.
symbol
}
/>
}
{
usd
&&
(
<
Skeleton
isLoaded=
{
!
isLoading
}
color=
"text
_
secondary"
loading=
{
isLoading
}
color=
"text
.
secondary"
wordBreak=
"break-all"
overflow=
"hidden"
>
...
...
ui/token/TokenTransfer/TokenTransferTable.tsx
View file @
6e4b3187
import
{
Table
,
Tbody
,
Tr
,
Th
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokenInfo
}
from
'
types/api/token
'
;
...
...
@@ -6,8 +5,8 @@ import type { TokenTransfer } from 'types/api/tokenTransfer';
import
{
AddressHighlightProvider
}
from
'
lib/contexts/addressHighlight
'
;
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
{
default
as
Thead
}
from
'
ui/shared/TheadSticky
'
;
import
TruncatedValue
from
'
ui/shared/TruncatedValue
'
;
import
TokenTransferTableItem
from
'
ui/token/TokenTransfer/TokenTransferTableItem
'
;
...
...
@@ -28,23 +27,23 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
return
(
<
AddressHighlightProvider
>
<
Table
minW=
"950px"
>
<
T
head
top=
{
top
}
>
<
T
r
>
<
T
h
width=
"280px"
>
Txn hash
</
Th
>
<
T
h
width=
"200px"
>
Method
</
Th
>
<
T
h
width=
{
{
lg
:
'
224px
'
,
xl
:
'
380px
'
}
}
>
From/To
</
Th
>
<
Table
Root
minW=
"950px"
>
<
T
ableHeaderSticky
top=
{
top
}
>
<
T
ableRow
>
<
T
ableColumnHeader
width=
"280px"
>
Txn hash
</
TableColumnHeader
>
<
T
ableColumnHeader
width=
"200px"
>
Method
</
TableColumnHeader
>
<
T
ableColumnHeader
width=
{
{
lg
:
'
224px
'
,
xl
:
'
380px
'
}
}
>
From/To
</
TableColumnHeader
>
{
(
NFT_TOKEN_TYPE_IDS
.
includes
(
tokenType
))
&&
<
T
h
width=
{
tokenType
===
'
ERC-1155
'
||
tokenType
===
'
ERC-404
'
?
'
50%
'
:
'
100%
'
}
>
Token ID
</
Th
>
<
T
ableColumnHeader
width=
{
tokenType
===
'
ERC-1155
'
||
tokenType
===
'
ERC-404
'
?
'
50%
'
:
'
100%
'
}
>
Token ID
</
TableColumnHeader
>
}
{
(
tokenType
===
'
ERC-20
'
||
tokenType
===
'
ERC-1155
'
||
tokenType
===
'
ERC-404
'
)
&&
(
<
T
h
width=
{
tokenType
===
'
ERC-20
'
?
'
100%
'
:
'
50%
'
}
isNumeric
>
<
T
ableColumnHeader
width=
{
tokenType
===
'
ERC-20
'
?
'
100%
'
:
'
50%
'
}
isNumeric
>
<
TruncatedValue
value=
{
`Value ${ token?.symbol || '' }`
}
w=
"100%"
verticalAlign=
"middle"
/>
</
T
h
>
</
T
ableColumnHeader
>
)
}
</
T
r
>
</
T
head
>
<
T
b
ody
>
</
T
ableRow
>
</
T
ableHeaderSticky
>
<
T
ableB
ody
>
{
showSocketInfo
&&
(
<
SocketNewItemsNotice
.
Desktop
url=
{
window
.
location
.
href
}
...
...
@@ -62,8 +61,8 @@ const TokenTransferTable = ({ data, top, showSocketInfo, socketInfoAlert, socket
isLoading=
{
isLoading
}
/>
))
}
</
T
b
ody
>
</
Table
>
</
T
ableB
ody
>
</
Table
Root
>
</
AddressHighlightProvider
>
);
};
...
...
ui/token/TokenTransfer/TokenTransferTableItem.tsx
View file @
6e4b3187
import
{
Tr
,
Td
,
Flex
,
Box
}
from
'
@chakra-ui/react
'
;
import
{
Flex
,
Box
}
from
'
@chakra-ui/react
'
;
import
React
from
'
react
'
;
import
type
{
TokenTransfer
}
from
'
types/api/tokenTransfer
'
;
import
getCurrencyValue
from
'
lib/getCurrencyValue
'
;
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
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
Tag
from
'
ui/shared/chakra/Tag
'
;
import
NftEntity
from
'
ui/shared/entities/nft/NftEntity
'
;
import
TxEntity
from
'
ui/shared/entities/tx/TxEntity
'
;
import
TimeAgoWithTooltip
from
'
ui/shared/TimeAgoWithTooltip
'
;
...
...
@@ -34,8 +35,8 @@ const TokenTransferTableItem = ({
})
:
{
usd
:
null
,
valueStr
:
null
};
return
(
<
T
r
alignItems=
"top"
>
<
T
d
>
<
T
ableRow
alignItems=
"top"
>
<
T
ableCell
>
<
Flex
alignItems=
"center"
py=
"7px"
>
<
TxEntity
hash=
{
txHash
}
...
...
@@ -54,15 +55,15 @@ const TokenTransferTableItem = ({
ml=
"10px"
/>
</
Flex
>
</
T
d
>
<
T
d
>
</
T
ableCell
>
<
T
ableCell
>
{
method
?
(
<
Box
my=
"3px"
>
<
Tag
isLoading=
{
isLoading
}
isTruncated
>
{
method
}
</
Tag
>
<
Badge
loading=
{
isLoading
}
truncated
>
{
method
}
</
Badge
>
</
Box
>
)
:
null
}
</
T
d
>
<
T
d
>
</
T
ableCell
>
<
T
ableCell
>
<
AddressFromTo
from=
{
from
}
to=
{
to
}
...
...
@@ -71,9 +72,9 @@ const TokenTransferTableItem = ({
mode=
{
{
lg
:
'
compact
'
,
xl
:
'
long
'
}
}
tokenHash=
{
token
?.
address
}
/>
</
T
d
>
</
T
ableCell
>
{
(
token
&&
NFT_TOKEN_TYPE_IDS
.
includes
(
token
.
type
))
&&
(
<
T
d
>
<
T
ableCell
>
{
total
&&
'
token_id
'
in
total
&&
token
&&
total
.
token_id
!==
null
?
(
<
NftEntity
hash=
{
token
.
address
}
...
...
@@ -83,23 +84,23 @@ const TokenTransferTableItem = ({
/>
)
:
''
}
</
T
d
>
</
T
ableCell
>
)
}
{
token
&&
(
token
.
type
===
'
ERC-20
'
||
token
.
type
===
'
ERC-1155
'
||
token
.
type
===
'
ERC-404
'
)
&&
(
<
T
d
isNumeric
verticalAlign=
"top"
>
<
T
ableCell
isNumeric
verticalAlign=
"top"
>
{
valueStr
&&
(
<
Skeleton
isLoaded=
{
!
isLoading
}
display=
"inline-block"
mt=
"7px"
wordBreak=
"break-all"
>
<
Skeleton
loading=
{
isLoading
}
display=
"inline-block"
mt=
"7px"
wordBreak=
"break-all"
>
{
valueStr
}
</
Skeleton
>
)
}
{
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
>
</
Skeleton
>
)
}
</
T
d
>
</
T
ableCell
>
)
}
</
T
r
>
</
T
ableRow
>
);
};
...
...
ui/token/TokenVerifiedInfo.tsx
View file @
6e4b3187
...
...
@@ -5,8 +5,8 @@ import type { TokenVerifiedInfo as TTokenVerifiedInfo } from 'types/api/token';
import
config
from
'
configs/app
'
;
import
type
{
ResourceError
}
from
'
lib/api/resources
'
;
import
Skeleton
from
'
ui/shared/chakra/Skeleton
'
;
import
LinkExternal
from
'
ui/shared/links/LinkExternal
'
;
import
{
Link
}
from
'
toolkit/chakra/link
'
;
import
{
Skeleton
}
from
'
toolkit/chakra/skeleton
'
;
import
TokenProjectInfo
from
'
./TokenProjectInfo
'
;
...
...
@@ -26,9 +26,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => {
if
(
isPending
)
{
return
(
<>
<
Skeleton
w=
"100px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
w=
"100px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
w=
"70px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
loading
w=
"100px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
loading
w=
"100px"
h=
"30px"
borderRadius=
"base"
/>
<
Skeleton
loading
w=
"70px"
h=
"30px"
borderRadius=
"base"
/>
</>
);
}
...
...
@@ -41,9 +41,9 @@ const TokenVerifiedInfo = ({ verifiedInfoQuery }: Props) => {
try
{
const
url
=
new
URL
(
data
.
projectWebsite
);
return
(
<
Link
External
href=
{
data
.
projectWebsite
}
variant=
"subtle"
flexShrink=
{
0
}
fontSize=
"sm"
lineHeight=
{
5
}
>
<
Link
external
href=
{
data
.
projectWebsite
}
variant=
"underlaid"
flexShrink=
{
0
}
textStyle=
"sm"
>
{
url
.
host
}
</
Link
External
>
</
Link
>
);
}
catch
(
error
)
{
return
null
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment