Skip to content

Commit

Permalink
Merge pull request #1530 from nervosnetwork/develop
Browse files Browse the repository at this point in the history
Merge develop into testnet
  • Loading branch information
Keith-CY authored Apr 1, 2024
2 parents d9ea4d6 + 1825c67 commit dcea3df
Show file tree
Hide file tree
Showing 13 changed files with 1,201 additions and 0 deletions.
6 changes: 6 additions & 0 deletions src/components/Header/MenusComp/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const useMenuDataList = () => {
type: LinkType.Inner,
name: t('navbar.tokens'),
children: [
// TODO: wait for API
// {
// type: LinkType.Inner,
// name: t('navbar.xUDT'),
// url: '/xudts',
// },
{
type: LinkType.Inner,
name: t('navbar.sUDT'),
Expand Down
15 changes: 15 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -647,6 +647,21 @@
"view_original": "View Original",
"repeat_inscription_symbol": "This inscription is a duplicate with an earlier release of the same symbol."
},
"xudt": {
"xudt": "xUDT",
"xudts": "xUDTs",
"name": "Name",
"symbol": "Symbol",
"total_amount": "Total Amount",
"issuer": "Issuer",
"type_script": "Type Script",
"holder_addresses": "Holder Addresses",
"decimal": "Decimal",
"transactions": "24hr Transactions",
"address_count": "Address Count",
"created_time": "Created Time",
"tokens_empty": "There are no xUDTs at this time."
},
"nft": {
"nft_collection": "NFT Collection",
"collection_name": "Collection Name",
Expand Down
15 changes: 15 additions & 0 deletions src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,21 @@
"view_original": "查看原铭文",
"repeat_inscription_symbol": "此铭文与早期发布的铭文同名"
},
"xudt": {
"xudt": "xUDT",
"xudts": "xUDTs",
"name": "名称",
"symbol": "符号",
"total_amount": "总量",
"issuer": "发行人",
"type_script": "Type Script",
"holder_addresses": "用户数",
"decimal": "小数位",
"transactions": "24小时交易数",
"address_count": "用户数",
"created_time": "创建时间",
"tokens_empty": "目前没有 xUDT。"
},
"nft": {
"nft_collection": "NFT 藏品",
"collection_name": "藏品名称",
Expand Down
16 changes: 16 additions & 0 deletions src/models/Xudt/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { Script } from '../Script'

export interface XUDT {
addressesCount: string
createdAt: string
h24CkbTransactionsCount: string
issuerAddress: string
published: boolean
decimal: string | null
fullName: string | null
symbol: string | null
totalAmount: string
typeHash: string
typeScript: Script
udtType: 'xudt'
}
165 changes: 165 additions & 0 deletions src/pages/Xudt/UDTComp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { Tooltip } from 'antd'
import { useTranslation } from 'react-i18next'
import { FC, useState } from 'react'
import { Link } from '../../components/Link'
import TransactionItem from '../../components/TransactionItem/index'
import { UDTTransactionsPagination, UDTTransactionsPanel, TypeScriptController, UDTNoResultPanel } from './styled'
import { parseUDTAmount } from '../../utils/number'
import { ReactComponent as OpenInNew } from '../../assets/open_in_new.svg'
import { deprecatedAddrToNewAddr } from '../../utils/util'
import styles from './styles.module.scss'
import AddressText from '../../components/AddressText'
import PaginationWithRear from '../../components/PaginationWithRear'
import { Transaction } from '../../models/Transaction'
import { Card, CardCellInfo, CardCellsLayout, HashCardHeader } from '../../components/Card'
import { useIsMobile } from '../../hooks'
import { isMainnet } from '../../utils/chain'
// TODO: replaced to svg format
import ArrowUpIcon from '../../assets/arrow_up.png'
import ArrowDownIcon from '../../assets/arrow_down.png'
import ArrowUpBlueIcon from '../../assets/arrow_up_blue.png'
import ArrowDownBlueIcon from '../../assets/arrow_down_blue.png'
import Script from '../../components/Script'
import { RawBtcRPC } from '../../services/ExplorerService'
import { XUDT } from '../../models/Xudt'

const typeScriptIcon = (show: boolean) => {
if (show) {
return isMainnet() ? ArrowUpIcon : ArrowUpBlueIcon
}
return isMainnet() ? ArrowDownIcon : ArrowDownBlueIcon
}

const IssuerContent: FC<{ address: string }> = ({ address }) => {
const { t } = useTranslation()
if (!address) {
return t('address.unable_decode_address')
}
const newAddress = deprecatedAddrToNewAddr(address)

return (
<>
<AddressText
linkProps={{
to: `/address/${newAddress}`,
}}
>
{newAddress}
</AddressText>

{newAddress !== address && (
<Tooltip placement="top" title={t(`udt.view-deprecated-address`)}>
<Link to={`/address/${address}`} className={styles.openInNew} target="_blank">
<OpenInNew />
</Link>
</Tooltip>
)}
</>
)
}

export const UDTOverviewCard = ({ typeHash, xudt }: { typeHash: string; xudt: XUDT | undefined }) => {
const { t } = useTranslation()
const isMobile = useIsMobile()
// const { fullName, issuerAddress, symbol, addressesCount, decimal, totalAmount, typeScript } = xudt
const [showType, setShowType] = useState(false)

const items: CardCellInfo<'left' | 'right'>[] = [
{
title: t('xudt.name'),
content: xudt?.fullName ?? '-',
},
{
title: t('xudt.issuer'),
contentWrapperClass: styles.addressWidthModify,
content: xudt ? <IssuerContent address={xudt.issuerAddress} /> : '-',
},
{
title: t('xudt.holder_addresses'),
content: xudt?.addressesCount ?? '-',
},
{
title: t('xudt.symbol'),
content: xudt?.symbol ?? '-',
},
{
title: t('xudt.decimal'),
content: xudt?.decimal ?? '-',
},
{
title: t('xudt.total_amount'),
content: xudt?.totalAmount && xudt?.decimal ? parseUDTAmount(xudt.totalAmount, xudt.decimal) : '-',
},
]

const cardTitle = <div className={styles.cardTitle}>{xudt?.symbol ?? t('xudt.xudt')}</div>

return (
<>
<Card className={styles.udtOverviewCard} style={{ marginBottom: 16 }}>
{/* When encountering more complex requirements, consider extracting the components within HashCardHeader
into smaller components. Then, implement a completely new variant or freely assemble them externally. */}
{isMobile && cardTitle}
<HashCardHeader className={styles.cardHeader} title={!isMobile && cardTitle} hash={typeHash} />

<CardCellsLayout type="left-right" cells={items} borderTop />

<TypeScriptController onClick={() => setShowType(!showType)}>
<div>{t('xudt.type_script')}</div>
<img alt="type script" src={typeScriptIcon(showType)} />
</TypeScriptController>
{showType && xudt?.typeScript && <Script script={xudt.typeScript} />}
</Card>
</>
)
}

export const UDTComp = ({
currentPage,
pageSize,
transactions,
total,
onPageChange,
filterNoResult,
}: {
currentPage: number
pageSize: number
transactions: (Transaction & { btcTx: RawBtcRPC.BtcTx | null })[]
total: number
onPageChange: (page: number) => void
filterNoResult?: boolean
}) => {
const { t } = useTranslation()
const totalPages = Math.ceil(total / pageSize)

if (filterNoResult) {
return (
<UDTNoResultPanel>
<span>{t('search.udt_filter_no_result')}</span>
</UDTNoResultPanel>
)
}
return (
<>
<UDTTransactionsPanel>
{transactions.map(
(transaction, index) =>
transaction && (
<TransactionItem
transaction={transaction}
key={transaction.transactionHash}
circleCorner={{
bottom: index === transactions.length - 1 && totalPages === 1,
}}
/>
),
)}
</UDTTransactionsPanel>
<UDTTransactionsPagination>
<PaginationWithRear currentPage={currentPage} totalPages={totalPages} onChange={onPageChange} rear={null} />
</UDTTransactionsPagination>
</>
)
}

export default UDTComp
107 changes: 107 additions & 0 deletions src/pages/Xudt/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import { useParams } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
import Content from '../../components/Content'
import { UDTContentPanel, UDTTransactionTitlePanel } from './styled'
import UDTComp, { UDTOverviewCard } from './UDTComp'
import { usePaginationParamsInPage, useSearchParams, useUpdateSearchParams } from '../../hooks'
import Filter from '../../components/Filter'
import { localeNumberString } from '../../utils/number'
import { explorerService } from '../../services/ExplorerService'
import { deprecatedAddrToNewAddr } from '../../utils/util'
import { QueryResult } from '../../components/QueryResult'
import styles from './styles.module.scss'
import { Cell } from '../../models/Cell'
import { assert } from '../../utils/error'

export const Xudt = () => {
const { t } = useTranslation()
// The typeHash here could be either udtTypeHash or omigaInscriptionInfoTypeHash.
const { hash: typeHash } = useParams<{ hash: string }>()
const { currentPage, pageSize: _pageSize, setPage } = usePaginationParamsInPage()

const { filter } = useSearchParams('filter')

const updateSearchParams = useUpdateSearchParams<'filter' | 'page'>()

const queryXudt = useQuery(['xudt', typeHash], () => explorerService.api.fetchXudt(typeHash))
const xudt = queryXudt.data

const querySimpleUDTTransactions = useQuery(
['xudt-transactions', typeHash, currentPage, _pageSize, filter],
async () => {
assert(typeHash)
const {
transactions,
total,
pageSize: resPageSize,
} = await explorerService.api.fetchUDTTransactions({
typeHash,
page: currentPage,
size: pageSize,
filter,
})

const ensureCellAddrIsNewFormat = (cell: Cell) => ({
...cell,
addressHash: deprecatedAddrToNewAddr(cell.addressHash),
})

return {
transactions: transactions.map(tx => ({
...tx,
displayInputs: tx.displayInputs.map(ensureCellAddrIsNewFormat),
displayOutputs: tx.displayOutputs.map(ensureCellAddrIsNewFormat),
})),
total,
pageSize: resPageSize,
}
},
{
enabled: typeHash != null,
},
)
const total = querySimpleUDTTransactions.data?.total ?? 0
const filterNoResult = !!filter && querySimpleUDTTransactions.isError
const pageSize: number = querySimpleUDTTransactions.data?.pageSize ?? _pageSize

return (
<Content>
<UDTContentPanel className="container">
<UDTOverviewCard typeHash={typeHash} xudt={xudt} />

<UDTTransactionTitlePanel>
<div className="udtTransactionContainer">
<div className="udtTransactionTitle">
{`${t('transaction.transactions')} (${localeNumberString(total)})`}
</div>
<div className={styles.searchAndfilter}>
<Filter
defaultValue={filter ?? ''}
showReset={!!filter}
placeholder={t('udt.search_placeholder')}
onFilter={filter => updateSearchParams(params => ({ ...params, filter }))}
onReset={() => updateSearchParams(params => ({ ...params, filter: null }))}
/>
</div>
</div>
</UDTTransactionTitlePanel>

<QueryResult query={querySimpleUDTTransactions} delayLoading>
{data => (
<UDTComp
currentPage={currentPage}
pageSize={pageSize}
transactions={data?.transactions ?? []}
total={data?.total ?? 0}
onPageChange={setPage}
filterNoResult={filterNoResult}
/>
)}
</QueryResult>
</UDTContentPanel>
</Content>
)
}

export default Xudt
Loading

0 comments on commit dcea3df

Please sign in to comment.