-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1530 from nervosnetwork/develop
Merge develop into testnet
- Loading branch information
Showing
13 changed files
with
1,201 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
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
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,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' | ||
} |
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,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 |
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,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 |
Oops, something went wrong.