diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index a6d7e0c..f7e7e2f 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -71,6 +71,9 @@
},
"backButton": "Go back"
},
+ "TOKENS": {
+ "title": "Tokens"
+ },
"FOOTER": {
"docs": "Documentation",
"github": "GitHub",
diff --git a/public/locales/es/common.json b/public/locales/es/common.json
index 7522d93..9041076 100644
--- a/public/locales/es/common.json
+++ b/public/locales/es/common.json
@@ -72,6 +72,9 @@
},
"backButton": "Volver"
},
+ "TOKENS": {
+ "title": "Tokens"
+ },
"FOOTER": {
"docs": "Documentación",
"github": "GitHub",
diff --git a/src/components/Table.tsx b/src/components/ChainTable.tsx
similarity index 98%
rename from src/components/Table.tsx
rename to src/components/ChainTable.tsx
index ba59ada..c99fbfa 100644
--- a/src/components/Table.tsx
+++ b/src/components/ChainTable.tsx
@@ -21,7 +21,7 @@ interface TableProps {
chains: EcosystemChainData[];
}
-export const DataTable = ({ chains }: TableProps) => {
+export const ChainTable = ({ chains }: TableProps) => {
const { t } = useTranslation();
const router = useRouter();
diff --git a/src/components/TVL.tsx b/src/components/TVL.tsx
index 6f1e8c6..235a705 100644
--- a/src/components/TVL.tsx
+++ b/src/components/TVL.tsx
@@ -30,6 +30,7 @@ export const TVL = () => {
{t('CHAIN.TVL.tvl')}
+
{tvl.map((token, index) => (
@@ -39,6 +40,7 @@ export const TVL = () => {
{token.name} ({token.symbol})
+
${token.price.toLocaleString()}
${((token.amountUsd * token.price) / 1e18).toLocaleString()}
diff --git a/src/components/TotalValueLocked.tsx b/src/components/TotalValueLocked.tsx
index 4d8a63d..33a3d69 100644
--- a/src/components/TotalValueLocked.tsx
+++ b/src/components/TotalValueLocked.tsx
@@ -1,13 +1,10 @@
import { Box, Typography, Grid, styled, useMediaQuery, useTheme } from '@mui/material';
import { useTranslation } from 'next-i18next';
-import { TvlData } from '~/types';
+
+import { TvlData, TotalValueLockedProps } from '~/types';
import { TvlContentBox } from '~/components';
import { useCustomTheme } from '~/hooks';
-interface TotalValueLockedProps {
- tvl: TvlData[];
-}
-
export const TotalValueLocked = ({ tvl }: TotalValueLockedProps) => {
const theme = useTheme();
const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
diff --git a/src/components/TvlContentBox.tsx b/src/components/TvlContentBox.tsx
index db48d30..b6aefac 100644
--- a/src/components/TvlContentBox.tsx
+++ b/src/components/TvlContentBox.tsx
@@ -19,6 +19,7 @@ export const TvlContentBox = ({ avatar, token, total, tokenName, isLast }: TvlCo
+
{tokenName}
{token}
diff --git a/src/components/index.ts b/src/components/index.ts
index 77249e1..b995248 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -1,6 +1,6 @@
export * from './Theme';
export * from './CustomHead';
-export * from './Table';
+export * from './ChainTable';
export * from './SearchBar';
export * from './TotalValueLocked';
export * from './Title';
diff --git a/src/containers/Dashboard/index.tsx b/src/containers/Dashboard/index.tsx
index fd0415f..9fd0f7e 100644
--- a/src/containers/Dashboard/index.tsx
+++ b/src/containers/Dashboard/index.tsx
@@ -1,7 +1,7 @@
import { useTranslation } from 'next-i18next';
import { Typography, styled } from '@mui/material';
-import { DataTable } from '~/components';
+import { ChainTable } from '~/components';
import { useData, useSearchContext, useCustomTheme } from '~/hooks';
export const Dashboard = () => {
@@ -38,7 +38,7 @@ export const Dashboard = () => {
{enterSearchTerm && {t('HOME.DASHBOARD.enterSearchTerm')}}
- {availableChains && }
+ {availableChains && }
{!availableChains && {t('HOME.DASHBOARD.notFound')}}
);
diff --git a/src/containers/Header/MobileHeader.tsx b/src/containers/Header/MobileHeader.tsx
index 6e8208c..845ed6f 100644
--- a/src/containers/Header/MobileHeader.tsx
+++ b/src/containers/Header/MobileHeader.tsx
@@ -39,6 +39,7 @@ export const MobileHeader = ({ theme, goToHome, handleChangeLanguage, localesMap
+
{theme === 'dark' ? (
@@ -47,10 +48,12 @@ export const MobileHeader = ({ theme, goToHome, handleChangeLanguage, localesMap
)}
+
{theme === 'dark' ? : }
+
+
+
+
{theme === 'dark' ? t('HEADER.lightMode') : t('HEADER.darkMode')}
diff --git a/src/containers/LockedAssets/index.tsx b/src/containers/LockedAssets/index.tsx
index 8459a2f..d5ad6c4 100644
--- a/src/containers/LockedAssets/index.tsx
+++ b/src/containers/LockedAssets/index.tsx
@@ -1,5 +1,6 @@
import { useTranslation } from 'next-i18next';
-import { Box, Typography, styled } from '@mui/material';
+import { useRouter } from 'next/router';
+import { Box, Typography, styled, Button } from '@mui/material';
import { TotalValueLocked } from '~/components';
import { useData, useCustomTheme } from '~/hooks';
@@ -8,6 +9,11 @@ import { formatDataNumber } from '~/utils';
export const LockedAssets = () => {
const { t } = useTranslation();
const { ecosystemData, totalL1TVL } = useData();
+ const router = useRouter();
+
+ const goToTokensPage = () => {
+ router.push('/tokens');
+ };
return (
@@ -18,9 +24,14 @@ export const LockedAssets = () => {
{t('HOME.LOCKEDASSETS.lockedAssets')}
{t('HOME.LOCKEDASSETS.lockedAssetsDescription')}
+
{formatDataNumber(totalL1TVL, 0, true, true)}
+
+
+ {t('HOME.LOCKEDASSETS.allTokens')} {' '}
+
>
)}
@@ -58,3 +69,26 @@ const TitleAmount = styled(Typography)(() => ({
fontWeight: 700,
lineHeight: '2.5rem',
}));
+
+const AllTokensButton = styled(Button)(() => {
+ const { currentTheme } = useCustomTheme();
+ return {
+ color: currentTheme.textPrimary,
+ backgroundColor: currentTheme.backgroundSecondary,
+ borderRadius: currentTheme.borderRadius,
+ padding: '0.5rem 1rem',
+ gap: currentTheme.gap,
+ width: '5.5rem',
+ textTransform: 'none',
+ fontSize: '0.75rem',
+ marginTop: '1.5rem',
+ alignItems: 'center',
+ };
+});
+
+export const ButtonContainer = styled(Box)(() => {
+ return {
+ display: 'flex',
+ justifyContent: 'center',
+ };
+});
diff --git a/src/containers/Tokens/SkeletonTokens.tsx b/src/containers/Tokens/SkeletonTokens.tsx
new file mode 100644
index 0000000..7f10428
--- /dev/null
+++ b/src/containers/Tokens/SkeletonTokens.tsx
@@ -0,0 +1,17 @@
+import { Box } from '@mui/material';
+import { Skeleton } from '@mui/material';
+
+export const SkeletonTokens = () => {
+ return (
+
+ {/* Breadcrumb Skeleton */}
+
+
+ {/* Title Skeleton */}
+
+
+ {/* Main Container Skeleton for Locked Assets */}
+
+
+ );
+};
diff --git a/src/containers/Tokens/TokensTable.tsx b/src/containers/Tokens/TokensTable.tsx
new file mode 100644
index 0000000..d9348e5
--- /dev/null
+++ b/src/containers/Tokens/TokensTable.tsx
@@ -0,0 +1,53 @@
+import { useTranslation } from 'next-i18next';
+import { Table, Typography } from '@mui/material';
+
+import { TotalValueLockedProps } from '~/types';
+import {
+ STableContainer,
+ STableHead,
+ STableRow,
+ STableCellHead,
+ STableCell,
+ STableBody,
+ LogoCell,
+ TokenAvatar,
+ STitle,
+} from '~/components';
+
+export const TokensTable = ({ tvl }: TotalValueLockedProps) => {
+ const { t } = useTranslation();
+
+ return (
+
+ {t('TOKENS.title')}
+
+
+
+
+ {t('CHAIN.TVL.chain')}
+ {t('CHAIN.TVL.price')}
+ {t('CHAIN.TVL.tvl')}
+
+
+
+
+ {tvl.map((token, index) => (
+
+
+
+
+ {token.tokenName} ({token.token})
+
+
+
+ ${token.price.toLocaleString()}
+
+ ${((token.total * token.price) / 1e18).toLocaleString()}
+
+ ))}
+
+
+
+
+ );
+};
diff --git a/src/containers/Tokens/index.tsx b/src/containers/Tokens/index.tsx
new file mode 100644
index 0000000..e3bf26e
--- /dev/null
+++ b/src/containers/Tokens/index.tsx
@@ -0,0 +1,35 @@
+import { styled } from '@mui/material';
+
+import { useData } from '~/hooks';
+import { Breadcrumb } from '~/components';
+import { TokensTable } from './TokensTable';
+import { SkeletonTokens } from './SkeletonTokens';
+
+export const Tokens = () => {
+ const { ecosystemData, isEcosystemLoading } = useData();
+ const tvl = ecosystemData?.l1Tvl || [];
+ return (
+
+ {isEcosystemLoading && }
+ {!isEcosystemLoading && (
+ <>
+
+
+ >
+ )}
+
+ );
+};
+
+const TokensContainer = styled('main')(({ theme }) => ({
+ padding: '0 7rem',
+ alignItems: 'center',
+ justifyContent: 'center',
+ width: '100%',
+ gap: '4rem',
+ marginTop: '4rem',
+ marginBottom: '4rem',
+ [theme.breakpoints.down('sm')]: {
+ padding: '0 1rem',
+ },
+}));
diff --git a/src/containers/index.ts b/src/containers/index.ts
index 2d86631..bf93c22 100644
--- a/src/containers/index.ts
+++ b/src/containers/index.ts
@@ -7,3 +7,4 @@ export * from './LockedAssets';
export * from './ChainDetail';
export * from './ChainDetail/ChainDescription';
export * from './ChainDetail/ChainMetadata';
+export * from './Tokens';
diff --git a/src/data/ecosystemMockData.json b/src/data/ecosystemMockData.json
index db23a4c..ef8d37f 100644
--- a/src/data/ecosystemMockData.json
+++ b/src/data/ecosystemMockData.json
@@ -4,48 +4,56 @@
"token": "ETH",
"tokenName": "Ethereum",
"total": 557596566000,
+ "price": 300,
"imageUrl": "https://dynamic-assets.coinbase.com/dbb4b4983bde81309ddab83eb598358eb44375b930b94687ebe38bc22e52c3b2125258ffb8477a5ef22e33d6bd72e32a506c391caa13af64c00e46613c3e5806/asset_icons/4113b082d21cc5fab17fc8f2d19fb996165bcce635e6900f7fc2d57c4ef33ae9.png"
},
{
"token": "USDT",
"tokenName": "Tether USD",
"total": 114493849618,
+ "price": 300,
"imageUrl": "https://www.cryptomkt.com/static/landing/img/crypto-pages/trending/usdt.svg"
},
{
"token": "USDC",
"tokenName": "Bridged USD",
"total": 34115209093,
+ "price": 300,
"imageUrl": "https://assets.coingecko.com/coins/images/6319/standard/usdc.png?1696506694"
},
{
"token": "KOI",
"tokenName": "Koi Finance",
"total": 24115209093,
+ "price": 300,
"imageUrl": "https://assets.coingecko.com/coins/images/35766/standard/Koi_logo.png?1709782399"
},
{
"token": "WBTC",
"tokenName": "Wrapped BTC",
"total": 12620248,
+ "price": 300,
"imageUrl": "https://assets.coingecko.com/coins/images/7598/standard/wrapped_bitcoin_wbtc.png?1696507857"
},
{
"token": "wstETH",
"tokenName": "Lido wstETH",
"total": 3552439,
+ "price": 300,
"imageUrl": "https://assets.coingecko.com/coins/images/18834/standard/wstETH.png?1696518295"
},
{
"token": "cbETH",
"tokenName": "Curve cbETH",
"total": 2552439,
+ "price": 300,
"imageUrl": "https://assets.coingecko.com/coins/images/27008/standard/cbeth.png?1709186989"
},
{
"token": "BAL",
"tokenName": "Balancer",
"total": 1552439,
+ "price": 300,
"imageUrl": "https://coin-images.coingecko.com/coins/images/671/large/balancer.png"
}
],
diff --git a/src/pages/tokens/index.tsx b/src/pages/tokens/index.tsx
new file mode 100644
index 0000000..2f29843
--- /dev/null
+++ b/src/pages/tokens/index.tsx
@@ -0,0 +1,32 @@
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
+import { GetStaticProps } from 'next';
+import { useTranslation } from 'next-i18next';
+
+import { CustomHead } from '~/components';
+import { Tokens } from '~/containers';
+import { getConfig } from '~/config';
+
+const { DEFAULT_LANG, SUPPORTED_LANGUAGES } = getConfig();
+
+const TokensPage = () => {
+ const { t } = useTranslation();
+
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export const getStaticProps: GetStaticProps = async ({ locale }) => {
+ const i18Config = await serverSideTranslations(locale || DEFAULT_LANG, ['common'], null, SUPPORTED_LANGUAGES);
+
+ return {
+ props: {
+ ...i18Config,
+ },
+ };
+};
+
+export default TokensPage;
diff --git a/src/types/Data.ts b/src/types/Data.ts
index aa67be7..22aff46 100644
--- a/src/types/Data.ts
+++ b/src/types/Data.ts
@@ -62,6 +62,7 @@ export interface TvlData {
symbol: string;
name: string;
amountUsd: number;
+ price: number;
imageUrl: string;
}
@@ -72,3 +73,6 @@ export interface ChainTvl {
imageUrl: string;
price: number;
}
+export interface TotalValueLockedProps {
+ tvl: TvlData[];
+}