-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Tokens page and dashboard component
- Loading branch information
Showing
10 changed files
with
419 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Add token overview page and dashboard component | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { FC } from 'react' | ||
import { Link as RouterLink } from 'react-router-dom' | ||
import Link from '@mui/material/Link' | ||
|
||
import { RouteUtils } from '../../utils/route-utils' | ||
import { TrimLinkLabel } from '../TrimLinkLabel' | ||
import { SearchScope } from '../../../types/searchScope' | ||
import { useScreenSize } from '../../hooks/useScreensize' | ||
|
||
export const TokenLink: FC<{ scope: SearchScope; address: string; name: string | undefined }> = ({ | ||
scope, | ||
address, | ||
name, | ||
}) => { | ||
const { isTablet } = useScreenSize() | ||
return isTablet ? ( | ||
<TrimLinkLabel label={name || address} to={RouteUtils.getTokenRoute(scope, address)} /> | ||
) : ( | ||
<Link component={RouterLink} to={RouteUtils.getTokenRoute(scope, address)}> | ||
{name || address} | ||
</Link> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import { useTranslation } from 'react-i18next' | ||
import { EvmToken } from '../../../oasis-indexer/api' | ||
import { Table, TableCellAlign, TableColProps } from '../../components/Table' | ||
import { TablePaginationProps } from '../Table/TablePagination' | ||
import { AccountLink } from '../Account/AccountLink' | ||
import { TokenLink } from './TokenLink' | ||
import { CopyToClipboard } from '../CopyToClipboard' | ||
|
||
type TokensProps = { | ||
tokens?: EvmToken[] | ||
isLoading: boolean | ||
limit: number | ||
verbose?: boolean | ||
pagination: false | TablePaginationProps | ||
} | ||
|
||
export const Tokens = (props: TokensProps) => { | ||
const { isLoading, tokens, pagination, limit } = props | ||
const { t } = useTranslation() | ||
const tableColumns: TableColProps[] = [ | ||
{ content: '' }, | ||
{ content: t('common.name') }, | ||
{ content: t('common.smartContract') }, | ||
{ | ||
content: t('tokens.holdersCount'), | ||
align: TableCellAlign.Right, | ||
}, | ||
{ content: t('tokens.supply'), align: TableCellAlign.Right }, | ||
{ content: t('common.ticker'), align: TableCellAlign.Right }, | ||
] | ||
|
||
const tableRows = tokens?.map((token, index) => { | ||
return { | ||
key: token.contract_addr, | ||
data: [ | ||
{ | ||
content: (index + 1).toLocaleString(), | ||
key: 'index', | ||
}, | ||
{ | ||
content: <TokenLink scope={token} address={token.evm_contract_addr} name={token.name} />, | ||
key: 'name', | ||
}, | ||
{ | ||
content: ( | ||
<span> | ||
<AccountLink scope={token} address={token.evm_contract_addr} /> | ||
<CopyToClipboard value={token.evm_contract_addr} /> | ||
</span> | ||
), | ||
key: 'contactAddress', | ||
}, | ||
{ | ||
content: token.num_holders.toLocaleString(), | ||
key: 'holdersCount', | ||
align: TableCellAlign.Right, | ||
}, | ||
{ | ||
content: token.total_supply, | ||
key: 'supply', | ||
align: TableCellAlign.Right, | ||
}, | ||
{ | ||
content: token.symbol, | ||
key: 'ticker', | ||
align: TableCellAlign.Right, | ||
}, | ||
], | ||
} | ||
}) | ||
|
||
return ( | ||
<Table | ||
columns={tableColumns} | ||
rows={tableRows} | ||
rowsNumber={limit} | ||
name={t('tokens.title')} | ||
isLoading={isLoading} | ||
pagination={pagination} | ||
/> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import React, { FC } from 'react' | ||
import { useTranslation } from 'react-i18next' | ||
import Card from '@mui/material/Card' | ||
import CardHeader from '@mui/material/CardHeader' | ||
import CardContent from '@mui/material/CardContent' | ||
import { Link as RouterLink } from 'react-router-dom' | ||
import Link from '@mui/material/Link' | ||
import { Layer, useGetRuntimeEvmTokens } from '../../../oasis-indexer/api' | ||
import { NUMBER_OF_ITEMS_ON_DASHBOARD } from '../../config' | ||
import { COLORS } from '../../../styles/theme/colors' | ||
import { AppErrors } from '../../../types/errors' | ||
import { useRequiredScopeParam } from '../../hooks/useScopeParam' | ||
import { RouteUtils } from '../../utils/route-utils' | ||
import { Tokens } from '../../components/Tokens' | ||
|
||
const limit = NUMBER_OF_ITEMS_ON_DASHBOARD | ||
|
||
export const TopTokens: FC = () => { | ||
const { t } = useTranslation() | ||
const scope = useRequiredScopeParam() | ||
const { network, layer } = scope | ||
if (layer === Layer.consensus) { | ||
throw AppErrors.UnsupportedLayer | ||
// Listing the latest consensus transactions is not yet supported. | ||
// We should use useGetConsensusTransactions() | ||
} | ||
const tokensQuery = useGetRuntimeEvmTokens(network, layer, { limit }) | ||
|
||
return ( | ||
<Card> | ||
<CardHeader | ||
disableTypography | ||
component="h3" | ||
title={t('tokens.title')} | ||
action={ | ||
<Link | ||
component={RouterLink} | ||
to={RouteUtils.getTopTokensRoute(scope)} | ||
sx={{ color: COLORS.brandExtraDark }} | ||
> | ||
{t('common.viewAll')} | ||
</Link> | ||
} | ||
/> | ||
<CardContent> | ||
<Tokens | ||
tokens={tokensQuery.data?.data.evm_tokens} | ||
isLoading={tokensQuery.isLoading} | ||
limit={limit} | ||
pagination={false} | ||
/> | ||
</CardContent> | ||
</Card> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
import { FC } from 'react' | ||
import { EvmToken } from '../../../oasis-indexer/api' | ||
import { TextSkeleton } from '../../components/Skeleton' | ||
|
||
// export const TokenDetailPage: FC = () => { | ||
// const { t } = useTranslation() | ||
// const scope = useRequiredScopeParam() | ||
// if (scope.layer === Layer.consensus) { | ||
// throw AppErrors.UnsupportedLayer | ||
// // We should use useGetConsensusBlocksHeight() | ||
// } | ||
// const blockHeight = parseInt(useParams().blockHeight!, 10) | ||
// const { isLoading, data } = useGetRuntimeBlockByHeight( | ||
// scope.network, | ||
// scope.layer, // This is OK, since consensus is already handled separately | ||
// blockHeight, | ||
// ) | ||
// if (!data && !isLoading) { | ||
// throw AppErrors.NotFoundBlockHeight | ||
// } | ||
// const block = data?.data | ||
// | ||
// return ( | ||
// <PageLayout> | ||
// <SubPageCard featured title={t('common.block')}> | ||
// <BlockDetailView isLoading={isLoading} block={block} /> | ||
// </SubPageCard> | ||
// {!!block?.num_transactions && <TransactionsCard scope={scope} blockHeight={blockHeight} />} | ||
// </PageLayout> | ||
// ) | ||
// } | ||
|
||
export const TokenDetailView: FC<{ | ||
isLoading?: boolean | ||
token: EvmToken | undefined | ||
showLayer?: boolean | ||
standalone?: boolean | ||
}> = ({ | ||
isLoading, | ||
token, | ||
// showLayer, | ||
// standalone = false | ||
}) => { | ||
// const { t } = useTranslation() | ||
// const { isMobile } = useScreenSize() | ||
|
||
if (isLoading) return <TextSkeleton numberOfRows={7} /> | ||
if (!token) return null | ||
|
||
return <div>Token details</div> | ||
// const transactionsAnchor = `${RouteUtils.getBlockRoute(block, block.round)}#${transactionsContainerId}` | ||
// const transactionLabel = block.num_transactions.toLocaleString() | ||
// const blockGasLimit = paraTimesConfig[block.layer]?.mainnet.blockGasLimit | ||
// if (!blockGasLimit) throw new Error('blockGasLimit is not configured') | ||
// return ( | ||
// <StyledDescriptionList | ||
// titleWidth={isMobile ? '100px' : '200px'} | ||
// standalone={standalone} | ||
// highlight={block.markAsNew} | ||
// > | ||
// {showLayer && ( | ||
// <> | ||
// <dt>{t('common.paratime')}</dt> | ||
// <dd> | ||
// <DashboardLink scope={block} /> | ||
// </dd> | ||
// </> | ||
// )} | ||
// <dt>{t('common.height')}</dt> | ||
// <dd> | ||
// <BlockLink scope={block} height={block.round} /> | ||
// <CopyToClipboard value={block.round.toString()} /> | ||
// </dd> | ||
// | ||
// <dt>{t('common.hash')}</dt> | ||
// <dd> | ||
// <BlockHashLink scope={block} hash={block.hash} height={block.round} /> | ||
// <CopyToClipboard value={block.hash.toString()} /> | ||
// </dd> | ||
// | ||
// <dt>{t('common.timestamp')}</dt> | ||
// <dd>{formattedTime}</dd> | ||
// | ||
// <dt>{t('common.size')}</dt> | ||
// <dd> | ||
// {t('common.bytes', { | ||
// value: block.size, | ||
// formatParams: { | ||
// value: { | ||
// style: 'unit', | ||
// unit: 'byte', | ||
// unitDisplay: 'long', | ||
// } satisfies Intl.NumberFormatOptions, | ||
// }, | ||
// })} | ||
// </dd> | ||
// | ||
// <dt>{t('common.transactions')}</dt> | ||
// <dd> | ||
// {block.num_transactions ? ( | ||
// <Link href={transactionsAnchor}>{transactionLabel}</Link> | ||
// ) : ( | ||
// transactionLabel | ||
// )} | ||
// </dd> | ||
// | ||
// <dt>{t('common.gasUsed')}</dt> | ||
// <dd> | ||
// {t('block.gasUsed', { | ||
// value: block.gas_used, | ||
// percentage: block.gas_used / blockGasLimit, | ||
// formatParams: { | ||
// percentage: { | ||
// style: 'percent', | ||
// maximumFractionDigits: 2, | ||
// } satisfies Intl.NumberFormatOptions, | ||
// }, | ||
// })} | ||
// </dd> | ||
// | ||
// <dt>{t('common.gasLimit')}</dt> | ||
// <dd>{blockGasLimit.toLocaleString()}</dd> | ||
// </StyledDescriptionList> | ||
// ) | ||
} |
Oops, something went wrong.