Skip to content

Commit

Permalink
feat: support view original inscription (#236)
Browse files Browse the repository at this point in the history
* feat: support view original inscription

* refactor: remove useless codes in the UDT page

* refactor: query param view_original=1 change to view=original

* fix: the params of the udt page are lost when filtering
  • Loading branch information
WhiteMinds authored Jan 31, 2024
1 parent 4342be6 commit d4303e0
Show file tree
Hide file tree
Showing 15 changed files with 106 additions and 149 deletions.
12 changes: 10 additions & 2 deletions src/components/CsvExport/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import styles from './styles.module.scss'
import { ReactComponent as ExportIcon } from './export_icon.svg'
import { SupportedExportTransactionType } from '../../services/ExplorerService'

export function CsvExport({ type, id }: { type: SupportedExportTransactionType; id?: string }) {
export function CsvExport({
type,
id,
isViewOriginal,
}: {
type: SupportedExportTransactionType
id?: string
isViewOriginal?: boolean
}) {
const [t] = useTranslation()
return (
<Link
className={styles.exportLink}
to={`/export-transactions?type=${type}${id ? `&id=${id}` : ''}`}
to={`/export-transactions?type=${type}${id ? `&id=${id}` : ''}${isViewOriginal ? '&view=original' : ''}`}
target="_blank"
>
<div>{t(`export_transactions.csv_export`)}</div>
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useCallback } from 'react'
import { useHistory, useLocation } from 'react-router-dom'
import { ListPageParams, PageParams } from '../constants/common'
import { omit } from '../utils/object'
import { omit, omitNil } from '../utils/object'

function getSearchParams<T extends string = string>(search: string, names?: T[]): Partial<Record<T, string>> {
const urlSearchParams = new URLSearchParams(search)
Expand Down Expand Up @@ -76,7 +76,7 @@ export function useSortParam<T extends string>(
}

export function useUpdateSearchParams<T extends string>(): (
updater: (current: Partial<Record<T, string>>) => Partial<Record<T, string>>,
updater: (current: Partial<Record<T, string>>) => Partial<Record<T, string | null | undefined>>,
replace?: boolean,
) => void {
const history = useHistory()
Expand All @@ -85,7 +85,7 @@ export function useUpdateSearchParams<T extends string>(): (
return useCallback(
(updater, replace) => {
const oldParams: Partial<Record<T, string>> = getSearchParams(search)
const newParams = updater(oldParams)
const newParams = omitNil(updater(oldParams))
const newUrlSearchParams = new URLSearchParams(newParams as Record<string, string>)
newUrlSearchParams.sort()
const newQueryString = newUrlSearchParams.toString()
Expand Down
3 changes: 2 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@
"mint_limit": "Mint Limit",
"mint_status_minting": "Minting",
"mint_status_closed": "Closed",
"mint_status_rebase_start": "Rebase Start"
"mint_status_rebase_start": "Rebase Start",
"view_original": "View Original"
},
"nft": {
"nft_collection": "NFT Collection",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -594,7 +594,8 @@
"mint_limit": "铸造限制",
"mint_status_minting": "铸造中",
"mint_status_closed": "已关闭",
"mint_status_rebase_start": "重铸开始"
"mint_status_rebase_start": "重铸开始",
"view_original": "查看原铭文"
},
"nft": {
"nft_collection": "NFT 藏品",
Expand Down
1 change: 1 addition & 0 deletions src/models/UDT/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export interface OmigaInscriptionCollection extends UDT {
mintLimit: string
expectedSupply: string
inscriptionInfoId: string
infoTypeHash: string
}

export function isOmigaInscriptionCollection(udt: UDT): udt is OmigaInscriptionCollection {
Expand Down
8 changes: 6 additions & 2 deletions src/pages/ExportTransactions/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,12 @@ const ExportTransactions = () => {
'end-date': endDateStr,
'from-height': fromHeightStr,
'to-height': toHeightStr,
} = useSearchParams('type', 'id', 'tab', 'start-date', 'end-date', 'from-height', 'to-height')
view,
} = useSearchParams('type', 'id', 'tab', 'start-date', 'end-date', 'from-height', 'to-height', 'view')
const isViewOriginal = view === 'original'

function isTransactionCsvExportType(s?: string): s is SupportedExportTransactionType {
return !!s && ['address_transactions', 'blocks', 'udts', 'nft'].includes(s)
return !!s && ['address_transactions', 'blocks', 'udts', 'nft', 'omiga_inscriptions'].includes(s)
}

const type = isTransactionCsvExportType(typeStr) ? typeStr : 'blocks'
Expand Down Expand Up @@ -122,6 +125,7 @@ const ExportTransactions = () => {
id,
date: tab === 'date' ? { start: startDate, end: endDate } : undefined,
block: tab === 'height' ? { from: fromHeight!, to: toHeight! } : undefined,
isViewOriginal,
})
.then((resp: string | null) => {
setIsDownloading(false)
Expand Down
4 changes: 3 additions & 1 deletion src/pages/Tokens/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ const TokenItem = ({ token, isLast }: { token: UDT | OmigaInscriptionCollection;
<Link
className={styles.link}
to={
isOmigaInscriptionCollection(token) ? `/inscription/${token.typeHash}` : `/sudt/${token.typeHash}`
isOmigaInscriptionCollection(token)
? `/inscription/${token.infoTypeHash}`
: `/sudt/${token.typeHash}`
}
>
{symbol}
Expand Down
24 changes: 21 additions & 3 deletions src/pages/UDT/UDTComp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import AddressText from '../../components/AddressText'
import PaginationWithRear from '../../components/PaginationWithRear'
import { CsvExport } from '../../components/CsvExport'
import { Transaction } from '../../models/Transaction'
import { OmigaInscriptionCollection, UDT, isOmigaInscriptionCollection } from '../../models/UDT'
import { OmigaInscriptionCollection, UDT, isOmigaInscriptionCollection, MintStatus } from '../../models/UDT'
import { Card, CardCellInfo, CardCellsLayout, HashCardHeader } from '../../components/Card'
import { useIsMobile } from '../../hooks'
import SUDTTokenIcon from '../../assets/sudt_token.png'
Expand All @@ -25,6 +25,7 @@ import ArrowUpBlueIcon from '../../assets/arrow_up_blue.png'
import ArrowDownBlueIcon from '../../assets/arrow_down_blue.png'
import Script from '../../components/Script'
import Capacity from '../../components/Capacity'
import { ReactComponent as ViewOriginalIcon } from './view_original.svg'

const typeScriptIcon = (show: boolean) => {
if (show) {
Expand Down Expand Up @@ -166,6 +167,20 @@ export const UDTOverviewCard = ({ typeHash, udt }: { typeHash: string; udt: UDT
className={styles.cardHeader}
title={!isMobile && cardTitle}
hash={typeHash}
customActions={[
isOmigaInscriptionCollection(udt) && udt.mintStatus === MintStatus.RebaseStart ? (
<Tooltip placement="top" title={t('udt.view_original')}>
<Link
to={`/inscription/${udt.infoTypeHash}?view=original`}
target="_blank"
rel="noopener noreferrer"
className={styles.viewOriginal}
>
<ViewOriginalIcon />
</Link>
</Tooltip>
) : null,
]}
rightContent={!isMobile && modifyTokenInfo}
/>

Expand All @@ -189,6 +204,7 @@ export const UDTComp = ({
filterNoResult,
id,
isInscription,
isViewOriginal,
}: {
currentPage: number
pageSize: number
Expand All @@ -198,6 +214,7 @@ export const UDTComp = ({
filterNoResult?: boolean
id: string
isInscription?: boolean
isViewOriginal?: boolean
}) => {
const { t } = useTranslation()
const totalPages = Math.ceil(total / pageSize)
Expand Down Expand Up @@ -230,8 +247,9 @@ export const UDTComp = ({
currentPage={currentPage}
totalPages={totalPages}
onChange={onPageChange}
// TODO: The backend has not yet implemented export support for Inscription (xUDT), so it is disabled for now.
rear={!isInscription && <CsvExport type="udts" id={id} />}
rear={
<CsvExport type={isInscription ? 'omiga_inscriptions' : 'udts'} id={id} isViewOriginal={isViewOriginal} />
}
/>
</UDTTransactionsPagination>
</>
Expand Down
91 changes: 22 additions & 69 deletions src/pages/UDT/index.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,53 @@
import { Link, useHistory, useLocation, useParams } from 'react-router-dom'
import { useParams } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
import { Popover } from 'antd'
import { FC } from 'react'
import Content from '../../components/Content'
import { UDTContentPanel, UDTTransactionTitlePanel } from './styled'
import UDTComp, { UDTOverviewCard } from './UDTComp'
import { useIsMobile, usePaginationParamsInPage } from '../../hooks'
import { usePaginationParamsInPage, useSearchParams, useUpdateSearchParams } from '../../hooks'
import Filter from '../../components/Search/Filter'
import { localeNumberString } from '../../utils/number'
import { explorerService } from '../../services/ExplorerService'
import { deprecatedAddrToNewAddr } from '../../utils/util'
import { QueryResult } from '../../components/QueryResult'
import { defaultUDTInfo } from './state'
import { ReactComponent as FilterIcon } from '../../assets/filter_icon.svg'
import { ReactComponent as SelectedCheckIcon } from '../../assets/selected_check_icon.svg'
import styles from './styles.module.scss'
import { Cell } from '../../models/Cell'

enum TransactionType {
Mint = 'mint',
Transfer = 'normal',
Burn = 'destruction',
}
import { assert } from '../../utils/error'

export const UDT: FC<{ isInscription?: boolean }> = ({ isInscription }) => {
const { t } = useTranslation()
const isMobile = useIsMobile()
const { push } = useHistory()
const { search } = useLocation()
// The typeHash here could be either udtTypeHash or omigaInscriptionInfoTypeHash.
const { hash: typeHash } = useParams<{ hash: string }>()
const { currentPage, pageSize: _pageSize, setPage } = usePaginationParamsInPage()

const query = new URLSearchParams(search)
const filter = query.get('filter')
const type = query.get('type')
const { filter, view } = useSearchParams('filter', 'view')
const isViewOriginal = view === 'original'

const queryUDT = useQuery(['udt', isInscription], () =>
isInscription ? explorerService.api.fetchOmigaInscription(typeHash) : explorerService.api.fetchSimpleUDT(typeHash),
const updateSearchParams = useUpdateSearchParams<'filter' | 'page'>()

const queryUDT = useQuery(['udt', isInscription, isViewOriginal], () =>
isInscription
? explorerService.api.fetchOmigaInscription(typeHash, isViewOriginal)
: explorerService.api.fetchSimpleUDT(typeHash),
)
const udt = queryUDT.data ?? defaultUDTInfo

const udtTypeHash = isInscription ? queryUDT.data?.typeHash : typeHash
const querySimpleUDTTransactions = useQuery(
['simple-udt-transactions', typeHash, currentPage, _pageSize, filter, type],
['simple-udt-transactions', udtTypeHash, currentPage, _pageSize, filter],
async () => {
assert(udtTypeHash)
const {
data: transactions,
total,
pageSize: resPageSize,
} = await explorerService.api.fetchUDTTransactions({
typeHash,
typeHash: udtTypeHash,
page: currentPage,
size: pageSize,
filter,
type,
})

const ensureCellAddrIsNewFormat = (cell: Cell) => ({
Expand All @@ -71,29 +65,14 @@ export const UDT: FC<{ isInscription?: boolean }> = ({ isInscription }) => {
pageSize: resPageSize,
}
},
{
enabled: udtTypeHash != null,
},
)
const total = querySimpleUDTTransactions.data?.total ?? 0
const filterNoResult = !!filter && querySimpleUDTTransactions.isError
const pageSize: number = querySimpleUDTTransactions.data?.pageSize ?? _pageSize

const filterList: { value: TransactionType; title: string }[] = [
{
value: TransactionType.Mint,
title: t('udt.view-mint-txns'),
},
{
value: TransactionType.Transfer,
title: t('udt.view-transfer-txns'),
},
{
value: TransactionType.Burn,
title: t('udt.view-burn-txns'),
},
]

const isFilteredByType = filterList.some(f => f.value === type)
const udtLinkPrefix = !isInscription ? '/sudt' : '/inscription'

return (
<Content>
<UDTContentPanel className="container">
Expand All @@ -109,36 +88,9 @@ export const UDT: FC<{ isInscription?: boolean }> = ({ isInscription }) => {
defaultValue={filter ?? ''}
showReset={!!filter}
placeholder={t('udt.search_placeholder')}
onFilter={filter => {
push(`${udtLinkPrefix}/${typeHash}?${new URLSearchParams({ filter })}`)
}}
onReset={() => {
push(`${udtLinkPrefix}/${typeHash}`)
}}
onFilter={filter => updateSearchParams(params => ({ ...params, filter }))}
onReset={() => updateSearchParams(params => ({ ...params, filter: null }))}
/>
<div className={styles.typeFilter} data-is-active={isFilteredByType}>
<Popover
placement="bottomRight"
trigger={isMobile ? 'click' : 'hover'}
overlayClassName={styles.antPopover}
content={
<div className={styles.filterItems}>
{filterList.map(f => (
<Link
key={f.value}
to={`${udtLinkPrefix}/${typeHash}?${new URLSearchParams({ type: f.value })}`}
data-is-active={f.value === type}
>
{f.title}
<SelectedCheckIcon />
</Link>
))}
</div>
}
>
<FilterIcon />
</Popover>
</div>
</div>
</div>
</UDTTransactionTitlePanel>
Expand All @@ -154,6 +106,7 @@ export const UDT: FC<{ isInscription?: boolean }> = ({ isInscription }) => {
filterNoResult={filterNoResult}
id={typeHash}
isInscription={isInscription}
isViewOriginal={isViewOriginal}
/>
)}
</QueryResult>
Expand Down
1 change: 1 addition & 0 deletions src/pages/UDT/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export const defaultOmigaInscriptionInfo: OmigaInscriptionCollection = {
mintLimit: '0',
expectedSupply: '0',
inscriptionInfoId: '',
infoTypeHash: '',
}
Loading

0 comments on commit d4303e0

Please sign in to comment.