diff --git a/.changelog/685.feature.md b/.changelog/685.feature.md
new file mode 100644
index 000000000..1cc98d4b4
--- /dev/null
+++ b/.changelog/685.feature.md
@@ -0,0 +1 @@
+Display type in tokens table
diff --git a/src/app/components/Tokens/TokenDetails.tsx b/src/app/components/Tokens/TokenDetails.tsx
index 9fe9f72d0..f351a9564 100644
--- a/src/app/components/Tokens/TokenDetails.tsx
+++ b/src/app/components/Tokens/TokenDetails.tsx
@@ -11,6 +11,7 @@ import { DashboardLink } from '../../pages/ParatimeDashboardPage/DashboardLink'
import { DelayedContractVerificationIcon } from '../ContractVerificationIcon'
import Box from '@mui/material/Box'
import { COLORS } from '../../../styles/theme/colors'
+import { TokenTypeTag } from './TokenList'
export const TokenDetails: FC<{
isLoading?: boolean
@@ -40,6 +41,11 @@ export const TokenDetails: FC<{
({token.symbol})
+
{t('common.type')}
+
+
+
+
{t(isMobile ? 'common.smartContract_short' : 'common.smartContract')}
diff --git a/src/app/components/Tokens/TokenList.tsx b/src/app/components/Tokens/TokenList.tsx
index baa2682af..9c964b57b 100644
--- a/src/app/components/Tokens/TokenList.tsx
+++ b/src/app/components/Tokens/TokenList.tsx
@@ -1,12 +1,22 @@
import { useTranslation } from 'react-i18next'
-import { EvmToken } from '../../../oasis-nexus/api'
+import { EvmToken, EvmTokenType } from '../../../oasis-nexus/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'
-import { DelayedContractVerificationIcon } from '../ContractVerificationIcon'
+import { DelayedContractVerificationIcon, verificationIconBoxHeight } from '../ContractVerificationIcon'
import Box from '@mui/material/Box'
+import {
+ getTokenTypeDescription,
+ getTokenTypeStrictName,
+ tokenBackgroundColor,
+ tokenBorderColor,
+} from '../../../types/tokens'
+import { FC } from 'react'
+import Typography from '@mui/material/Typography'
+import { COLORS } from '../../../styles/theme/colors'
+import { SxProps } from '@mui/material/styles'
type TokensProps = {
tokens?: EvmToken[]
@@ -15,12 +25,40 @@ type TokensProps = {
pagination: false | TablePaginationProps
}
+export const TokenTypeTag: FC<{ tokenType: EvmTokenType; sx?: SxProps }> = ({ tokenType, sx = {} }) => {
+ const { t } = useTranslation()
+ return (
+
+ {getTokenTypeDescription(t, tokenType)}
+
+
+ {t('common.parentheses', { subject: getTokenTypeStrictName(t, tokenType) })}
+
+
+ )
+}
+
export const TokenList = (props: TokensProps) => {
const { isLoading, tokens, pagination, limit } = props
const { t } = useTranslation()
const tableColumns: TableColProps[] = [
{ key: 'index', content: '' },
{ key: 'name', content: t('common.name') },
+ { key: 'type', content: t('common.type') },
{ key: 'contract', content: t('common.smartContract') },
{ key: 'verification', content: t('contract.verification.title') },
{
@@ -54,6 +92,10 @@ export const TokenList = (props: TokensProps) => {
),
key: 'name',
},
+ {
+ key: 'type',
+ content: ,
+ },
{
content: (
diff --git a/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx
index 9d3735efa..e9d330e66 100644
--- a/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx
+++ b/src/app/pages/AccountDetailsPage/AccountTokensCard.tsx
@@ -16,6 +16,11 @@ import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useAccount } from './hook'
import { TokenLink } from '../../components/Tokens/TokenLink'
import { AccountLink } from '../../components/Account/AccountLink'
+import {
+ getTokenTypePluralDescription,
+ getTokenTypePluralName,
+ getTokenTypeStrictName,
+} from '../../../types/tokens'
type AccountTokensCardProps = {
type: EvmTokenType
@@ -28,8 +33,7 @@ export const AccountTokensCard: FC = ({ type }) => {
const address = useLoaderData() as string
const { t } = useTranslation()
const locationHash = useLocation().hash.replace('#', '')
- const tokenLabel = t(`account.${type}` as any)
- const tokenListLabel = t('account.tokensListTitle', { token: tokenLabel })
+ const tokenListLabel = getTokenTypePluralName(t, type)
const tableColumns: TableColProps[] = [
{ key: 'name', content: t('common.name') },
{ key: 'contract', content: t('common.smartContract') },
@@ -86,7 +90,12 @@ export const AccountTokensCard: FC = ({ type }) => {
{!isLoading && !account?.tokenBalances[type]?.length && (
-
+
)}
{
const { t } = useTranslation()
@@ -65,12 +66,12 @@ export const AccountDetailsPage: FC = () => {
{ label: t('common.transactions'), to: txLink, visible: showTxs },
{ label: t('tokens.transfers'), to: tokenTransfersLink, visible: showTokenTransfers },
{
- label: t('account.tokensListTitle', { token: t(`account.ERC20`) }),
+ label: getTokenTypePluralName(t, EvmTokenType.ERC20),
to: erc20Link,
visible: showErc20,
},
{
- label: t('account.tokensListTitle', { token: t(`account.ERC721`) }),
+ label: getTokenTypePluralName(t, EvmTokenType.ERC721),
to: erc721Link,
visible: showErc721,
},
diff --git a/src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx b/src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
index e67326b8e..5a0b07778 100644
--- a/src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
+++ b/src/app/pages/TokenDashboardPage/TokenDetailsCard.tsx
@@ -11,10 +11,10 @@ import { useTranslation } from 'react-i18next'
import { AccountLink } from '../../components/Account/AccountLink'
import { CopyToClipboard } from '../../components/CopyToClipboard'
import { DelayedContractVerificationIcon } from '../../components/ContractVerificationIcon'
-import { getTokenTypeName } from './TokenTypeCard'
import { getNameForTicker, Ticker } from '../../../types/ticker'
import { DelayedContractCreatorInfo } from '../../components/Account/ContractCreatorInfo'
import CardContent from '@mui/material/CardContent'
+import { TokenTypeTag } from '../../components/Tokens/TokenList'
export const TokenDetailsCard: FC = () => {
const { t } = useTranslation()
@@ -57,7 +57,9 @@ export const TokenDetailsCard: FC = () => {
{t('common.type')}
- {getTokenTypeName(t, token.type)}
+
+
+
{t('contract.creator')}
diff --git a/src/app/pages/TokenDashboardPage/TokenTypeCard.tsx b/src/app/pages/TokenDashboardPage/TokenTypeCard.tsx
index e6f8fc2c0..ef363d8a6 100644
--- a/src/app/pages/TokenDashboardPage/TokenTypeCard.tsx
+++ b/src/app/pages/TokenDashboardPage/TokenTypeCard.tsx
@@ -7,21 +7,7 @@ import { COLORS } from '../../../styles/theme/colors'
import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { useTokenInfo } from './hook'
import { useLoaderData } from 'react-router-dom'
-import { EvmTokenType } from '../../../oasis-nexus/api'
-import { TFunction } from 'i18next'
-import { exhaustedTypeWarning } from '../../../types/errors'
-
-export const getTokenTypeName = (t: TFunction, type: EvmTokenType): string => {
- switch (type) {
- case 'ERC20':
- return t('account.ERC20')
- case 'ERC721':
- return t('account.ERC721')
- default:
- exhaustedTypeWarning('Unknown token type', type)
- return type
- }
-}
+import { getTokenTypeName } from '../../../types/tokens'
export const TokenTypeCard: FC = () => {
const { t } = useTranslation()
@@ -32,7 +18,7 @@ export const TokenTypeCard: FC = () => {
const { token, isFetched } = useTokenInfo(scope, address)
return (
-
+
{isFetched && (
<>
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 628185992..da847e3fc 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -2,7 +2,7 @@
"appName": "Oasis Explorer",
"account": {
"cantLoadDetails": "Unfortunately we couldn't load the account details at this time. Please try again later.",
- "emptyTokenList": "This account holds no {{token}} tokens.",
+ "emptyTokenList": "This account holds no {{spec}} {{description}}.",
"emptyTransactionList": "There are no transactions on record for this account.",
"emptyTokenTransferList": "There are no token transfers on record for this account.",
"ERC20": "ERC-20",
@@ -10,7 +10,6 @@
"noTokens": "This account holds no tokens",
"showMore": "+ {{counter}} more",
"title": "Account",
- "tokensListTitle": "{{token}} Tokens",
"transactionsListTitle": "Account Transactions",
"totalReceived": "Total Received",
"totalSent": "Total Sent"
@@ -65,8 +64,11 @@
"lessThanAmount": "< {{value}} {{ticker}}",
"missing": "n/a",
"name": "Name",
+ "nft": "NFT",
+ "nfts": "NFTs",
"oasis": "Oasis",
"paratime": "Paratime",
+ "parentheses":"({{subject}})",
"percentage": "Percentage",
"rank": "Rank",
"select": "Select",
@@ -203,6 +205,7 @@
"request": "Request test tokens"
},
"tokens": {
+ "typeDescription": "{{description}} ({{spec}})",
"emptyTokenHolderList": "There are no token holders on record for this token.",
"holders": "Token Holders",
"holdersValue": "{{ value, number }}",
diff --git a/src/styles/theme/colors.ts b/src/styles/theme/colors.ts
index 9cc323a80..92c0060e6 100644
--- a/src/styles/theme/colors.ts
+++ b/src/styles/theme/colors.ts
@@ -10,6 +10,7 @@ export const COLORS = {
brandExtraLight: '#e5e5ef',
brandLight: '#6665d8',
brandMedium: '#0092f6',
+ brandMedium15: '#d9effe',
brightGray2: '#ececec',
brightGray: '#e6edf3',
ceil: '#8f8cdf',
@@ -51,4 +52,6 @@ export const COLORS = {
graphLabel: '#191932',
graphLine: '#01F1E3',
paraTimeStatus: '#8081ac',
+ pink: '#ed32fa',
+ pink15: '#fce0fe',
} satisfies { [colorName: string]: string }
diff --git a/src/types/tokens.ts b/src/types/tokens.ts
new file mode 100644
index 000000000..f09a59f07
--- /dev/null
+++ b/src/types/tokens.ts
@@ -0,0 +1,62 @@
+import { EvmTokenType } from '../oasis-nexus/api'
+import { TFunction } from 'i18next'
+import { exhaustedTypeWarning } from './errors'
+import { COLORS } from '../styles/theme/colors'
+
+export const getTokenTypeDescription = (t: TFunction, tokenType: EvmTokenType): string => {
+ switch (tokenType) {
+ case 'ERC20':
+ return t('common.token')
+ case 'ERC721':
+ return t('common.nft')
+ default:
+ exhaustedTypeWarning('Unknown token type', tokenType)
+ return '???'
+ }
+}
+
+export const tokenBackgroundColor: Record = {
+ ERC20: COLORS.brandMedium15,
+ ERC721: COLORS.pink15,
+}
+
+export const tokenBorderColor: Record = {
+ ERC20: COLORS.brandMedium,
+ ERC721: COLORS.pink,
+}
+
+export const getTokenTypePluralDescription = (t: TFunction, tokenType: EvmTokenType): string => {
+ switch (tokenType) {
+ case 'ERC20':
+ return t('common.tokens')
+ case 'ERC721':
+ return t('common.nfts')
+ default:
+ exhaustedTypeWarning('Unknown token type', tokenType)
+ return '???'
+ }
+}
+
+export const getTokenTypeStrictName = (t: TFunction, tokenType: EvmTokenType): string => {
+ switch (tokenType) {
+ case 'ERC20':
+ return t('account.ERC20')
+ case 'ERC721':
+ return t('account.ERC721')
+ default:
+ exhaustedTypeWarning('Unknown token type', tokenType)
+ return tokenType
+ }
+}
+
+export const getTokenTypeName = (t: TFunction, tokenType: EvmTokenType): string =>
+ t('tokens.typeDescription', {
+ spec: getTokenTypeStrictName(t, tokenType),
+ description: getTokenTypeDescription(t, tokenType),
+ })
+
+export const getTokenTypePluralName = (t: TFunction, tokenType: EvmTokenType): string =>
+ t('tokens.typeDescription', {
+ spec: getTokenTypeStrictName(t, tokenType),
+ description: getTokenTypePluralDescription(t, tokenType),
+ })