diff --git a/api/api_list.ts b/api/api_list.ts index e24cdac7..7572e214 100644 --- a/api/api_list.ts +++ b/api/api_list.ts @@ -5,6 +5,9 @@ const API_LIST = { BLOCKS: '/blocks/', TRANSACTION_OF_BLOCK: '/blocks/:id/transactions?pagination=offset&page=1&limit=20&order=height.desc', LATEST_BLOCK: 'evm_/api/v1?module=block&action=eth_block_number', + ALL_TOKENS: 'evm_/api/v1?module=token&action=getListTokens', // &page=1&offset=20 + ALL_HOLDERS: + 'evm_/api/v1?module=token&action=getTokenHolders&contractaddress=0x60baCCdfdCa114f97F32121f6b2879fB555Df4d0&page=1&offset=20', // &page=1&offset=20 ALL_TRANSACTIONS: '/transactions', TRANSACTIONS: '/transactions/', diff --git a/package.json b/package.json index 030fac1d..625bc70d 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "license": "MIT", "dependencies": { "@astradefi/address-converter": "^0.4.1", - "@astraprotocol/astra-ui": "file:/Users/lap02631/astra/astra-ui", + "@astraprotocol/astra-ui": "file:../../Github/astra-ui", "@cosmjs/crypto": "^0.29.0", "@cosmjs/encoding": "^0.29.0", "@reduxjs/toolkit": "^1.8.5", diff --git a/pages/accounts.tsx b/pages/accounts.tsx index ee791869..0d3efe55 100644 --- a/pages/accounts.tsx +++ b/pages/accounts.tsx @@ -1,35 +1,46 @@ import Container from 'components/Container' +import { PageTitle } from 'components/Typography/PageTitle' +import RowTitle from 'components/Typography/RowTitle' import { NextPage } from 'next' +// import {Pagination} from '@astraprotocol/astra-ui' import Head from 'next/head' -import React from 'react' +import React, { useState } from 'react' import Layout from '../components/Layout' -const AccountsPage: React.FC = _ => { - // // const t = useTranslations('Index') +const AstraHolderPage: React.FC = _ => { + const [currentPage, setPage] = useState(1) + // const { tokens } = useTokens(currentPage) + // console.log(tokens) return ( Astra Explorer - Account + + + Astra Address + + {/* */} + {/* {!tokens || tokens.length === 0 ? ( + + ) : ( +
+ {tokens?.map((item: Token, index: number) => { + return + })} +
+ )} */} +
) } -// // type HomeExtendProps = typeof Home & { messages: string[] } -// // ;(Home as HomeExtendProps).messages = ['Index'] -// // export async function getStaticProps({ locale }: GetStaticPropsContext) { -// // return { -// // props: { -// // messages: pick( -// // { -// // ...(await import(`../messages/share/${locale}.json`)).default, -// // ...(await import(`../messages/index/${locale}.json`)).default -// // }, -// // (Home as HomeExtendProps).messages -// // ) -// // } -// // } -// // } -export default AccountsPage +export default AstraHolderPage diff --git a/pages/token/[token].tsx b/pages/token/[token].tsx new file mode 100644 index 00000000..e69de29b diff --git a/pages/tokens.tsx b/pages/tokens.tsx index e2f08187..d6f29742 100644 --- a/pages/tokens.tsx +++ b/pages/tokens.tsx @@ -1,35 +1,50 @@ import Container from 'components/Container' +import RowLoader from 'components/Loader/RowLoader' +import { PageTitle } from 'components/Typography/PageTitle' +import RowTitle from 'components/Typography/RowTitle' import { NextPage } from 'next' +// import {Pagination} from '@astraprotocol/astra-ui' import Head from 'next/head' -import React from 'react' +import React, { useState } from 'react' +import useTokens from 'views/tokens/hook/useTokens' +import TokenRow from 'views/tokens/TokenRow' import Layout from '../components/Layout' const AllTokensPage: React.FC = _ => { - // // const t = useTranslations('Index') + const [currentPage, setPage] = useState(1) + const { tokens } = useTokens(currentPage) + console.log(tokens) return ( Astra Explorer - Token + + + Tokens + + {/* */} + {!tokens || tokens.length === 0 ? ( + + ) : ( +
+ {tokens?.map((item: Token, index: number) => { + return + })} +
+ )} +
) } -// // type HomeExtendProps = typeof Home & { messages: string[] } -// // ;(Home as HomeExtendProps).messages = ['Index'] -// // export async function getStaticProps({ locale }: GetStaticPropsContext) { -// // return { -// // props: { -// // messages: pick( -// // { -// // ...(await import(`../messages/share/${locale}.json`)).default, -// // ...(await import(`../messages/index/${locale}.json`)).default -// // }, -// // (Home as HomeExtendProps).messages -// // ) -// // } -// // } -// // } export default AllTokensPage diff --git a/project.d.ts b/project.d.ts index 62f81463..0fa01210 100644 --- a/project.d.ts +++ b/project.d.ts @@ -367,3 +367,21 @@ interface CosmosTransactionDetailResponse { } status: string } + +interface Token { + cataloged: boolean + contract_address_hash: string + decimals: string + holder_count: number + name: string + skip_metadata: any + symbol: string + total_supply: string + type: string +} + +interface TokenResponse { + message: string + result: Token[] + status: string +} diff --git a/utils/helper.ts b/utils/helper.ts index 1e5c83c0..6ef4cbb7 100644 --- a/utils/helper.ts +++ b/utils/helper.ts @@ -77,13 +77,23 @@ export class LinkMaker { /** * - * @param blockNumber empty -> block homepage + * @param hash + * @param query * @returns */ static transaction(hash?: string, query: string = '') { hash = hash ? `/${hash}${query}` : '' return `/tx${hash}` } + + /** + * + * @param token + * @returns + */ + static token(token: string) { + return `/token/${token}` + } } /** diff --git a/views/accounts/TokenRow.tsx b/views/accounts/TokenRow.tsx new file mode 100644 index 00000000..f632868c --- /dev/null +++ b/views/accounts/TokenRow.tsx @@ -0,0 +1,77 @@ +import clsx from 'clsx' +import Typography from 'components/Typography' +import { LinkMaker } from 'utils/helper' +import styles from './style.module.scss' + +type Props = { + index: number + token: Token + // blockNumber: number + // size: number + // updatedAt: number | string + // transactions: number + // proposerAddress: string + // mine?: boolean + // value: number + // newBlock?: boolean +} + +export default function TokenRow({ + index, + token +}: // blockNumber, +// updatedAt, +// transactions, +// proposerAddress, +// mine, +// size, +// value, +// newBlock +Props) { + return ( +
+
{index}
+
+ + {`${token.name} (${token.symbol})`} + +
+ +
+
+ + {token.contract_address_hash} + +
+ {/*
+ {10000} + USDT +
*/} +
+ +
+ {token.total_supply} + {token.symbol} +
+ +
+ {token.holder_count} +
+
+ ) +} diff --git a/views/accounts/hook/useAccounts.ts b/views/accounts/hook/useAccounts.ts new file mode 100644 index 00000000..3f2b0cbd --- /dev/null +++ b/views/accounts/hook/useAccounts.ts @@ -0,0 +1,27 @@ +import API_LIST from 'api/api_list' +import { useEffect, useState } from 'react' +import useSWR from 'swr' + +export default function useAccounts(page: number) { + const [tokens, setState] = useState() + + const _fetchCondition = () => { + return [ + API_LIST.ALL_HOLDERS, + { + page, + offset: 20 + } + ] + } + const { data } = useSWR(_fetchCondition()) + + useEffect(() => { + if (data?.result) { + setState(data?.result) + } + }, [data]) + return { + tokens + } +} diff --git a/views/accounts/style.module.scss b/views/accounts/style.module.scss new file mode 100644 index 00000000..43093409 --- /dev/null +++ b/views/accounts/style.module.scss @@ -0,0 +1,34 @@ +.rowBrief { + display: flex; + align-items: center; + .indexCenter { + display: flex; + align-items: center; + } + .content { + width: 100%; + .info { + display: flex; + justify-content: space-between; + } + } +} + +.tokenRow { + background: rgba(var(--contrast-color-theme--raw), 0.05); + border: 1px solid rgba(var(--contrast-color-theme--raw), 0.05); + backdrop-filter: blur(42px); + + .currency { + font-family: 'TitilliumWeb-SemiBold'; + color: var(--contrast-color-theme-70); + } +} +.borderLeft { + border-left: 1px solid rgba(var(--contrast-color-theme--raw), 0.05); +} + +.topRow { + display: flex; + justify-content: space-between; +} diff --git a/views/tokens/TokenRow.tsx b/views/tokens/TokenRow.tsx new file mode 100644 index 00000000..f632868c --- /dev/null +++ b/views/tokens/TokenRow.tsx @@ -0,0 +1,77 @@ +import clsx from 'clsx' +import Typography from 'components/Typography' +import { LinkMaker } from 'utils/helper' +import styles from './style.module.scss' + +type Props = { + index: number + token: Token + // blockNumber: number + // size: number + // updatedAt: number | string + // transactions: number + // proposerAddress: string + // mine?: boolean + // value: number + // newBlock?: boolean +} + +export default function TokenRow({ + index, + token +}: // blockNumber, +// updatedAt, +// transactions, +// proposerAddress, +// mine, +// size, +// value, +// newBlock +Props) { + return ( +
+
{index}
+
+ + {`${token.name} (${token.symbol})`} + +
+ +
+
+ + {token.contract_address_hash} + +
+ {/*
+ {10000} + USDT +
*/} +
+ +
+ {token.total_supply} + {token.symbol} +
+ +
+ {token.holder_count} +
+
+ ) +} diff --git a/views/tokens/hook/useTokens.ts b/views/tokens/hook/useTokens.ts new file mode 100644 index 00000000..4c01c2fa --- /dev/null +++ b/views/tokens/hook/useTokens.ts @@ -0,0 +1,27 @@ +import API_LIST from 'api/api_list' +import { useEffect, useState } from 'react' +import useSWR from 'swr' + +export default function useTokens(page: number) { + const [tokens, setState] = useState() + + const _fetchCondition = () => { + return [ + API_LIST.ALL_TOKENS, + { + page, + offset: 20 + } + ] + } + const { data } = useSWR(_fetchCondition()) + + useEffect(() => { + if (data?.result) { + setState(data?.result) + } + }, [data]) + return { + tokens + } +} diff --git a/views/tokens/style.module.scss b/views/tokens/style.module.scss new file mode 100644 index 00000000..43093409 --- /dev/null +++ b/views/tokens/style.module.scss @@ -0,0 +1,34 @@ +.rowBrief { + display: flex; + align-items: center; + .indexCenter { + display: flex; + align-items: center; + } + .content { + width: 100%; + .info { + display: flex; + justify-content: space-between; + } + } +} + +.tokenRow { + background: rgba(var(--contrast-color-theme--raw), 0.05); + border: 1px solid rgba(var(--contrast-color-theme--raw), 0.05); + backdrop-filter: blur(42px); + + .currency { + font-family: 'TitilliumWeb-SemiBold'; + color: var(--contrast-color-theme-70); + } +} +.borderLeft { + border-left: 1px solid rgba(var(--contrast-color-theme--raw), 0.05); +} + +.topRow { + display: flex; + justify-content: space-between; +}