Skip to content

Commit

Permalink
Merge pull request #1476 from nervosnetwork/develop
Browse files Browse the repository at this point in the history
Merge develop into testnet
  • Loading branch information
Keith-CY authored Mar 12, 2024
2 parents f44c19e + 69a8cf9 commit 9d23241
Show file tree
Hide file tree
Showing 7 changed files with 316 additions and 8 deletions.
7 changes: 4 additions & 3 deletions src/components/Search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ const Search: FC<{
content?: string
hasButton?: boolean
onEditEnd?: () => void
}> = memo(({ content, hasButton, onEditEnd: handleEditEnd }) => {
onClear?: () => void
}> = memo(({ content, hasButton, onEditEnd: handleEditEnd, onClear: handleClear }) => {
const history = useHistory()
const queryClient = useQueryClient()
const { t } = useTranslation()
Expand Down Expand Up @@ -118,8 +119,8 @@ const Search: FC<{
const onClear = useCallback(() => {
setKeyword('')
resetSearchByName()
setEditEnded(true)
}, [resetSearchByName, setEditEnded])
handleClear?.()
}, [resetSearchByName, handleClear])

return (
<SearchPanel moreHeight={hasButton} hasButton={hasButton}>
Expand Down
2 changes: 2 additions & 0 deletions src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@
"hash_type": "Hash Type",
"overview": "Overview",
"user_defined_token": "Simple User Defined Token",
"cell": "Cell",
"cells": "Cells",
"inscription": "Inscription",
"confirmation": "Confirmation",
"confirmations": "Confirmations",
Expand Down
2 changes: 2 additions & 0 deletions src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@
"hash_type": "Hash Type",
"overview": "概览",
"user_defined_token": "Simple User Defined Token",
"cell": "Cell",
"cells": "Cells",
"inscription": "铭文",
"confirmation": "确认区块",
"confirmations": "确认区块",
Expand Down
40 changes: 35 additions & 5 deletions src/pages/Address/AddressComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import { Transaction } from '../../models/Transaction'
import { Address, UDTAccount } from '../../models/Address'
import { Card, CardCellInfo, CardCellsLayout } from '../../components/Card'
import { CardHeader } from '../../components/Card/CardHeader'
import Cells from './Cells'
import {
AddressCoTAComp,
AddressOmigaInscriptionComp,
Expand All @@ -57,6 +58,7 @@ import {
enum AssetInfo {
UDT = 1,
INSCRIPTION,
CELLs,
}

const lockScriptIcon = (show: boolean) => {
Expand Down Expand Up @@ -188,19 +190,30 @@ export const AddressOverviewCard: FC<{ address: Address }> = ({ address }) => {
},
]

const hasAssets = udts.length > 0 || (cotaList?.length && cotaList.length > 0)
const hasInscriptions = inscriptions.length > 0
const hasCells = +address.liveCellsCount > 0

useEffect(() => {
if (!udts.length && !cotaList?.length && inscriptions.length) {
if (hasAssets) {
return
}
if (hasInscriptions) {
setActiveTab(AssetInfo.INSCRIPTION)
return
}
}, [udts.length, cotaList?.length, inscriptions.length])
if (hasCells) {
setActiveTab(AssetInfo.CELLs)
}
}, [hasAssets, hasInscriptions, hasCells, setActiveTab])

return (
<Card className={styles.addressOverviewCard}>
<div className={styles.cardTitle}>{t('address.overview')}</div>

<CardCellsLayout type="leftSingle-right" cells={overviewItems} borderTop />

{udts.length > 0 || (cotaList?.length && cotaList.length > 0) || inscriptions.length > 0 ? (
{hasAssets || hasInscriptions || hasCells ? (
<AddressUDTAssetsPanel className={styles.addressUDTAssetsPanel}>
<AddressAssetsTab animated={false} key={i18n.language} activeKey={activeTab.toString()}>
{(udts.length > 0 || cotaList?.length) && (
Expand Down Expand Up @@ -244,7 +257,7 @@ export const AddressOverviewCard: FC<{ address: Address }> = ({ address }) => {
</div>
</AddressAssetsTabPane>
)}
{inscriptions.length > 0 && (
{hasInscriptions ? (
<AddressAssetsTabPane
tab={
<AddressAssetsTabPaneTitle onClick={() => setActiveTab(AssetInfo.INSCRIPTION)}>
Expand All @@ -270,7 +283,22 @@ export const AddressOverviewCard: FC<{ address: Address }> = ({ address }) => {
})}
</div>
</AddressAssetsTabPane>
)}
) : null}

{hasCells ? (
<AddressAssetsTabPane
tab={
<AddressAssetsTabPaneTitle onClick={() => setActiveTab(AssetInfo.CELLs)}>
{t(`address.${+address.liveCellsCount > 1 ? 'cells' : 'cell'}`)}
</AddressAssetsTabPaneTitle>
}
key={AssetInfo.CELLs}
>
<div className="addressUdtAssetsGrid">
<Cells address={address.addressHash} count={+address.liveCellsCount} />
</div>
</AddressAssetsTabPane>
) : null}
</AddressAssetsTab>
</AddressUDTAssetsPanel>
) : null}
Expand Down Expand Up @@ -410,3 +438,5 @@ export const AddressTransactions = ({
</>
)
}

// FIXME: plural in i18n not work, address.cell and address.cells
161 changes: 161 additions & 0 deletions src/pages/Address/Cells.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import { type FC, useState, useRef, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { useInfiniteQuery } from '@tanstack/react-query'
import { explorerService } from '../../services/ExplorerService'
import styles from './cells.module.scss'
import { shannonToCkb } from '../../utils/util'
import { parseUDTAmount } from '../../utils/number'
import SUDTTokenIcon from '../../assets/sudt_token.png'
import CKBTokenIcon from './ckb_token_icon.png'

const fetchCells = async ({
address,
size = 10,
sort = 'capacity.desc',
page = 1,
}: {
address: string
size: number
sort: string
page: number
}) => {
const res = await explorerService.api.fetchAddressLiveCells(address, page, size, sort)
return {
data: res.data,
nextPage: page + 1,
}
}

const initialPageParams = { size: 10, sort: 'capacity.desc' }

const Cells: FC<{ address: string; count: number }> = ({ address, count }) => {
const [params] = useState(initialPageParams)
const loadMoreRef = useRef<HTMLDivElement | null>(null)

const { t } = useTranslation()

const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = useInfiniteQuery(
['address live cells', address, params.size, params.sort],
({ pageParam = 1 }) => fetchCells({ ...params, address, page: pageParam }),
{
getNextPageParam: lastPage => {
if (lastPage.data.length < params.size) return false
return lastPage.nextPage
},
},
)

const isListDisplayed = count && data

useEffect(() => {
const trigger = loadMoreRef.current

if (!isListDisplayed) return
const observer = new IntersectionObserver(
entries => {
if (entries[0].isIntersecting) {
fetchNextPage()
}
},
{ threshold: 0.5 },
)
if (trigger) {
observer.observe(trigger)
}
return () => {
if (trigger) {
observer.unobserve(trigger)
}
}
}, [isListDisplayed, fetchNextPage])

if (!isListDisplayed) {
return null
}

const cells = data.pages.map(page => page.data).flat()

return (
<div className={styles.container}>
<div className={styles.toolbar}>UTXO: {count.toLocaleString('en')}</div>
<ul>
{cells.map(cell => {
const ckb = Number(shannonToCkb(cell.capacity)).toLocaleString('en')
const title = `${cell.txHash.slice(0, 8)}...${cell.txHash.slice(-8)}#${cell.cellIndex}`
const link = `/transaction/${cell.txHash}`
const assetType: string = cell.extraInfo?.type ?? cell.cellType
let icon = null
let assetName = null
let assetAmount = null
switch (assetType) {
case 'ckb': {
if (cell.data !== '0x') {
// TODO: indicate this is a contentful cell
icon = SUDTTokenIcon
assetName = 'UNKNOWN'
assetAmount = '-'
break
}
icon = CKBTokenIcon
assetName = 'CKB'
assetAmount = ckb
break
}
case 'udt':
case 'omiga_inscription': {
icon = SUDTTokenIcon
assetName = cell.extraInfo.symbol || t('udt.inscription')
assetAmount = cell.extraInfo.decimal
? parseUDTAmount(cell.extraInfo.amount, cell.extraInfo.decimal)
: 'Unknown UDT amount'
break
}
case 'spore_cell': {
icon = SUDTTokenIcon
assetName = 'Spore'
assetAmount = '-'
break
}
case 'nrc_721': {
icon = SUDTTokenIcon
assetName = 'NRC 721'
assetAmount = '-'
break
}
default: {
icon = SUDTTokenIcon
assetName = 'UNKNOWN'
assetAmount = '-'
// ignore
}
}

return (
<li key={cell.txHash + cell.cellIndex} className={styles.card}>
<h5>
<a href={link}>{title}</a>
<span>{`${ckb} CKB`}</span>
</h5>
<div className={styles.content}>
{icon ? <img src={icon} alt={assetName ?? 'sudt'} width="40" height="40" /> : null}
<div>
<div className={styles.assetName}>{assetName}</div>
<div>{assetAmount}</div>
</div>
</div>
</li>
)
})}
</ul>
{isFetchingNextPage ? <span className={styles.loading}>Loading...</span> : null}
{!hasNextPage || isFetchingNextPage ? null : (
<div className={styles.loadMore} ref={loadMoreRef}>
<button type="button" onClick={() => fetchNextPage()}>
Load more
</button>
</div>
)}
</div>
)
}
export default Cells
78 changes: 78 additions & 0 deletions src/pages/Address/cells.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.container {
width: 100%;
height: 310px;
overflow: scroll;

.toolbar {
margin-top: 1rem;
margin-bottom: 1rem;
}

ul {
list-style: none;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(248px, 1fr));
gap: 1rem;
}
}

.card {
flex-basis: 248px;
min-height: 86px;
background: #fff;
border-radius: 4px;
overflow: hidden;

h5 {
display: flex;
justify-content: space-between;
align-items: center;
background: var(--primary-color);
color: #fff;
height: 1.875rem;
padding: 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

&:hover {
a {
font-weight: bold;
color: #fff;
text-decoration: underline;
}
}
}

.content {
padding: 8px;
display: flex;

img {
margin-right: 8px;
}

.assetName {
color: #666;
}
}
}

.loading {
display: flex;
justify-content: center;
padding: 0.5rem;
}

.loadMore {
display: flex;
justify-content: center;
padding: 0.5rem;

button {
cursor: pointer;
appearance: none;
border: none;
}
}
Loading

0 comments on commit 9d23241

Please sign in to comment.