Skip to content

Commit

Permalink
Merge pull request #1069 from oasisprotocol/mz/nftTweaks
Browse files Browse the repository at this point in the history
NFT tweaks and fixes
  • Loading branch information
buberdds authored Dec 13, 2023
2 parents e72f0d1 + eaf1a70 commit f7aaef3
Show file tree
Hide file tree
Showing 27 changed files with 317 additions and 115 deletions.
1 change: 1 addition & 0 deletions .changelog/1069.feature.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add NFT feature
19 changes: 8 additions & 11 deletions src/app/components/Account/ContractCreatorInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { FC } from 'react'
import { SearchScope } from '../../../types/searchScope'
import { Trans, useTranslation } from 'react-i18next'
import { useTranslation } from 'react-i18next'
import { TransactionLink } from '../Transactions/TransactionLink'
import {
Layer,
Expand All @@ -12,6 +12,7 @@ import { AppErrors } from '../../../types/errors'
import { AccountLink } from './AccountLink'
import Box from '@mui/material/Box'
import Skeleton from '@mui/material/Skeleton'
import { useScreenSize } from '../../hooks/useScreensize'

const TxSender: FC<{ scope: SearchScope; txHash: string }> = ({ scope, txHash }) => {
const { t } = useTranslation()
Expand Down Expand Up @@ -42,6 +43,7 @@ export const ContractCreatorInfo: FC<{
creationTxHash: string | undefined
}> = ({ scope, isLoading, creationTxHash }) => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()

return isLoading ? (
<Skeleton variant="text" sx={{ width: '50%' }} />
Expand All @@ -51,20 +53,15 @@ export const ContractCreatorInfo: FC<{
<Box
sx={{
display: 'flex',
alignItems: 'center',
gap: 3,
flexDirection: isMobile ? 'column' : 'row',
alignItems: isMobile ? 'flex-start' : 'center',
gap: isMobile ? 0 : 2,
minWidth: '25%',
}}
>
<TxSender scope={scope} txHash={creationTxHash} />
&nbsp;
<Trans
t={t}
i18nKey="contract.createdAt"
components={{
TransactionLink: <TransactionLink scope={scope} hash={creationTxHash} alwaysTrim />,
}}
/>
<Box>{t('contract.createdAt')}</Box>
<TransactionLink scope={scope} hash={creationTxHash} alwaysTrim />
</Box>
)
}
Expand Down
14 changes: 9 additions & 5 deletions src/app/components/AppendMobileSearch/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ interface AppendMobileSearchProps {
action?: ReactNode
}

interface AppendMobileSearchLayoutProps {
action?: ReactNode
isMobile: boolean
}

const Layout = styled(Box, {
shouldForwardProp: (prop: PropertyKey) =>
!(['action'] as (keyof AppendMobileSearchProps)[]).includes(prop as keyof AppendMobileSearchProps),
})<AppendMobileSearchProps>(({ action }) => ({
shouldForwardProp: prop => prop !== 'action' && prop !== 'isMobile',
})<AppendMobileSearchLayoutProps>(({ action, isMobile }) => ({
position: 'relative',
alignItems: 'flex-start',
alignItems: isMobile ? 'center' : 'flex-start',
width: '100%',
...(action
? {
Expand All @@ -41,7 +45,7 @@ export const AppendMobileSearch: FC<PropsWithChildren<AppendMobileSearchProps> &
const { isMobile } = useScreenSize()

return (
<Layout action={action}>
<Layout action={action} isMobile={isMobile}>
<Box>{children}</Box>

{action}
Expand Down
29 changes: 29 additions & 0 deletions src/app/components/CardHeaderWithCounter/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { FC } from 'react'
import Box from '@mui/material/Box'
import Typography from '@mui/material/Typography'
import { COLORS } from 'styles/theme/colors'

type CardHeaderWithCounterProps = {
label: string | undefined
totalCount: number | undefined
isTotalCountClipped: boolean | undefined
}

export const CardHeaderWithCounter: FC<CardHeaderWithCounterProps> = ({
label,
totalCount,
isTotalCountClipped,
}) => {
return (
<Box sx={{ display: 'flex', alignItems: 'baseline' }} gap={2}>
<Typography color={COLORS.brandExtraDark} fontSize={24}>
{label}
</Typography>
{!!totalCount && (
<Typography color={COLORS.grayMedium}>
({`${isTotalCountClipped ? ' > ' : ''}${totalCount}`})
</Typography>
)}
</Box>
)
}
1 change: 1 addition & 0 deletions src/app/components/NoPreview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const NoPreview: FC<NoPreviewProps> = ({ placeholderSize }) => {
height: placeholderSize,
width: placeholderSize,
display: 'flex',
flex: 1,
justifyContent: 'center',
flexDirection: 'column',
alignItems: 'center',
Expand Down
18 changes: 16 additions & 2 deletions src/app/components/ProgressBar/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import LinearProgress from '@mui/material/LinearProgress'
import MuiLinearProgress, { linearProgressClasses } from '@mui/material/LinearProgress'
import { styled } from '@mui/material/styles'
import { COLORS } from 'styles/theme/colors'

export const VerticalProgressBar = styled(LinearProgress)(() => ({
export const VerticalProgressBar = styled(MuiLinearProgress)(() => ({
[`&.${linearProgressClasses.determinate} > .${linearProgressClasses.bar1Determinate}`]: {
backgroundColor: COLORS.brandDark,
},
height: 36,
width: 36,
transform: 'rotate(-90deg)',
}))

export const ProgressBar = styled(MuiLinearProgress)(() => ({
[`&.${linearProgressClasses.determinate} > .${linearProgressClasses.bar1Determinate}`]: {
backgroundColor: COLORS.eucalyptus,
},
borderColor: COLORS.eucalyptus,
backgroundColor: COLORS.honeydew,
height: '12px',
width: '85px',
}))
17 changes: 9 additions & 8 deletions src/app/components/Tokens/TokenDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { VerificationIcon } from '../ContractVerificationIcon'
import Box from '@mui/material/Box'
import { COLORS } from '../../../styles/theme/colors'
import { TokenTypeTag } from './TokenList'
import { getPreciseNumberFormat } from '../../../locales/getPreciseNumberFormat'
import { RoundedBalance } from '../RoundedBalance'

export const TokenDetails: FC<{
isLoading?: boolean
Expand All @@ -39,7 +39,9 @@ export const TokenDetails: FC<{
<dt>{t('common.name')}</dt>
<dd>
<TokenLink scope={token} address={token.eth_contract_addr ?? token.contract_addr} name={token.name} />
<Box sx={{ ml: 3, fontWeight: 700, color: COLORS.grayMedium }}>({token.symbol})</Box>
<Box sx={{ ml: 3, fontWeight: 700, color: COLORS.grayMedium, whiteSpace: 'nowrap' }}>
({token.symbol})
</Box>
</dd>

<dt>{t('common.type')}</dt>
Expand All @@ -64,12 +66,11 @@ export const TokenDetails: FC<{

<dt>{t('tokens.totalSupply')}</dt>
<dd>
{token.total_supply
? t('tokens.totalSupplyValue', {
...getPreciseNumberFormat(token.total_supply),
ticker: token.symbol,
})
: t('common.missing')}
{token.total_supply ? (
<RoundedBalance compactLargeNumbers value={token.total_supply} />
) : (
t('common.missing')
)}
</dd>
</StyledDescriptionList>
)
Expand Down
27 changes: 20 additions & 7 deletions src/app/components/Tokens/TokenHolders.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import Box from '@mui/material/Box'
import { Table, TableCellAlign, TableColProps } from '../Table'
import { BareTokenHolder } from '../../../oasis-nexus/api'
import { TablePaginationProps } from '../Table/TablePagination'
import { AccountLink } from '../Account/AccountLink'
import { fromBaseUnits } from '../../utils/helpers'
import { RoundedBalance } from '../RoundedBalance'
import { ProgressBar } from '../ProgressBar'

type TableTokenHolder = BareTokenHolder & {
markAsNew?: boolean
Expand All @@ -30,16 +32,14 @@ export const TokenHolders: FC<TokenHoldersProps> = ({
}) => {
const { t } = useTranslation()
const tableColumns: TableColProps[] = [
{ key: 'rank', content: t('common.rank'), align: TableCellAlign.Center },
{ key: 'rank', content: t('common.rank') },
{ key: 'address', content: t('common.address') },
{ key: 'quantity', content: t('common.quantity'), align: TableCellAlign.Right },
{ key: 'percentage', content: t('common.percentage'), align: TableCellAlign.Right },
]

const calculateRatio = (balance: string): string => {
return totalSupply === undefined
? t('common.missing')
: `${((100 * parseFloat(fromBaseUnits(balance, decimals))) / parseFloat(totalSupply)).toFixed(4)}%`
const calculateRatio = (balance: string, totalSupply: string, decimals: number): number => {
return (100 * parseFloat(fromBaseUnits(balance, decimals))) / parseFloat(totalSupply)
}

const tableRows = holders?.map((holder, index) => {
Expand All @@ -49,7 +49,6 @@ export const TokenHolders: FC<TokenHoldersProps> = ({
{
key: 'rank',
content: holder.rank.toLocaleString(),
align: TableCellAlign.Center,
},
{
key: 'address',
Expand All @@ -64,7 +63,21 @@ export const TokenHolders: FC<TokenHoldersProps> = ({
},
{
key: 'percentage',
content: calculateRatio(holder.balance),
content: (
<>
{totalSupply ? (
<Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }} gap={4}>
{`${calculateRatio(holder.balance, totalSupply, decimals).toFixed(4)}%`}
<ProgressBar
value={calculateRatio(holder.balance, totalSupply, decimals)}
variant="determinate"
/>
</Box>
) : (
<Box>{t('common.missing')}</Box>
)}
</>
),
align: TableCellAlign.Right,
},
],
Expand Down
8 changes: 6 additions & 2 deletions src/app/components/Tokens/TokenList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const TokenList = (props: TokensProps) => {
{ key: 'verification', content: t('contract.verification.title') },
{
key: 'holders',
content: t('tokens.holdersCount'),
content: t('tokens.holdersCount_short'),
align: TableCellAlign.Right,
},
{ key: 'supply', content: t('tokens.totalSupply'), align: TableCellAlign.Right },
Expand Down Expand Up @@ -98,7 +98,11 @@ export const TokenList = (props: TokensProps) => {
},
{
key: 'type',
content: <TokenTypeTag tokenType={token.type} sx={{ width: '100%' }} />,
content: (
<Box sx={{ pr: 4 }}>
<TokenTypeTag tokenType={token.type} sx={{ width: '100%' }} />
</Box>
),
},
{
content: (
Expand Down
7 changes: 7 additions & 0 deletions src/app/components/Tokens/TokenTransfers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { TokenLink } from './TokenLink'
import { PlaceholderLabel } from '../../utils/PlaceholderLabel'
import { TokenTypeTag } from './TokenList'
import { parseEvmEvent } from '../../utils/parseEvmEvent'
import { formatDistanceToNow } from '../../utils/dateFormatter'

const iconSize = '28px'
const StyledCircle = styled(Box)(({ theme }) => ({
Expand Down Expand Up @@ -119,6 +120,7 @@ export const TokenTransfers: FC<TokenTransfersProps> = ({
const tableColumns: TableColProps[] = [
{ key: 'hash', content: t('common.hash') },
{ key: 'block', content: t('common.block') },
{ key: 'timestamp', content: t('common.age'), align: TableCellAlign.Right },
{ key: 'type', content: t('common.type'), align: TableCellAlign.Center },
{ key: 'from', content: t('common.from'), width: '150px' },
{ key: 'to', content: t('common.to'), width: '150px' },
Expand Down Expand Up @@ -147,6 +149,11 @@ export const TokenTransfers: FC<TokenTransfersProps> = ({
content: <BlockLink scope={transfer} height={transfer.round} />,
key: 'round',
},
{
align: TableCellAlign.Right,
content: formatDistanceToNow(new Date(transfer.timestamp)),
key: 'timestamp',
},
{
key: 'type',
align: TableCellAlign.Center,
Expand Down
15 changes: 6 additions & 9 deletions src/app/pages/AccountDetailsPage/AccountNFTCollectionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import { AccountDetailsContext } from './index'
import { AccountLink } from 'app/components/Account/AccountLink'
import { CopyToClipboard } from 'app/components/CopyToClipboard'
import { RouteUtils } from 'app/utils/route-utils'
import { COLORS } from 'styles/theme/colors'
import { ImageListItemImage } from '../TokenDashboardPage/ImageListItemImage'
import { CardEmptyState } from '../AccountDetailsPage/CardEmptyState'
import { TablePagination } from '../../components/Table/TablePagination'
import { useAccountTokenInventory } from '../TokenDashboardPage/hook'
import { EvmNft } from 'oasis-nexus/api'
import { SearchScope } from '../../../types/searchScope'
import { NFTCollectionLink, NFTInstanceLink } from '../TokenDashboardPage/NFTLinks'
import { CardHeaderWithCounter } from 'app/components/CardHeaderWithCounter'

export const accountNFTCollectionContainerId = 'nftCollection'

Expand Down Expand Up @@ -63,14 +63,11 @@ export const AccountNFTCollectionCard: FC<AccountDetailsContext> = ({ scope, add
</Link>
</Typography>
{isFetched && (
<Box sx={{ display: 'flex', alignItems: 'baseline' }} gap={2}>
<Typography color={COLORS.brandExtraDark} fontSize={24}>
{firstToken?.name ? inventory?.[0].token.name : t('common.collection')}
</Typography>
{!!totalCount && (
<Typography>({`${isTotalCountClipped ? ' > ' : ''}${totalCount}`})</Typography>
)}
</Box>
<CardHeaderWithCounter
label={firstToken?.name ? inventory?.[0].token.name : t('common.collection')}
totalCount={totalCount}
isTotalCountClipped={isTotalCountClipped}
/>
)}
</Breadcrumbs>
{isLoading && <Skeleton variant="text" sx={{ width: '50%' }} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,10 @@ export const InstanceDetailsCard: FC<InstanceDetailsCardProps> = ({
</dd>
</>
)}
{nft?.token?.num_transfers && (
{nft?.num_transfers && (
<>
<dt>{t('nft.transfers')}</dt>
<dd>{nft.token.num_transfers!.toLocaleString()}</dd>
<dd>{nft.num_transfers.toLocaleString()}</dd>
</>
)}
<dt>{t(isMobile ? 'common.smartContract_short' : 'common.smartContract')}</dt>
Expand Down
11 changes: 3 additions & 8 deletions src/app/pages/NFTInstanceDashboardPage/NFTMetadataCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,18 @@ import { FC } from 'react'
import { useTranslation } from 'react-i18next'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import { Runtime, useGetRuntimeEvmTokensAddressNftsId } from '../../../oasis-nexus/api'
import { LinkableDiv } from '../../components/PageLayout/LinkableDiv'
import { CardEmptyState } from './../AccountDetailsPage/CardEmptyState'
import { NftDashboardContext } from '../NFTInstanceDashboardPage'
import { JsonCodeDisplay } from '../../components/CodeDisplay'
import { useNFTInstance } from '../TokenDashboardPage/hook'

export const nftMetadataId = 'metadata'

export const NFTMetadataCard: FC<NftDashboardContext> = ({ scope, address, instanceId }) => {
const { t } = useTranslation()
const { data, isFetched } = useGetRuntimeEvmTokensAddressNftsId(
scope.network,
scope.layer as Runtime,
address,
instanceId,
)
const metadata = data?.data?.metadata
const { isFetched, nft } = useNFTInstance(scope, address, instanceId)
const metadata = nft?.metadata

return (
<Card>
Expand Down
Loading

0 comments on commit f7aaef3

Please sign in to comment.