diff --git a/src/components/CsvExport/index.tsx b/src/components/CsvExport/index.tsx
index 01625ee9f..676e70719 100644
--- a/src/components/CsvExport/index.tsx
+++ b/src/components/CsvExport/index.tsx
@@ -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 (
{t(`export_transactions.csv_export`)}
diff --git a/src/hooks/route.ts b/src/hooks/route.ts
index 72de13af1..958ca9a4d 100644
--- a/src/hooks/route.ts
+++ b/src/hooks/route.ts
@@ -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(search: string, names?: T[]): Partial> {
const urlSearchParams = new URLSearchParams(search)
@@ -76,7 +76,7 @@ export function useSortParam(
}
export function useUpdateSearchParams(): (
- updater: (current: Partial>) => Partial>,
+ updater: (current: Partial>) => Partial>,
replace?: boolean,
) => void {
const history = useHistory()
@@ -85,7 +85,7 @@ export function useUpdateSearchParams(): (
return useCallback(
(updater, replace) => {
const oldParams: Partial> = getSearchParams(search)
- const newParams = updater(oldParams)
+ const newParams = omitNil(updater(oldParams))
const newUrlSearchParams = new URLSearchParams(newParams as Record)
newUrlSearchParams.sort()
const newQueryString = newUrlSearchParams.toString()
diff --git a/src/locales/en.json b/src/locales/en.json
index 6e4eb60c6..c070bc3b2 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -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",
diff --git a/src/locales/zh.json b/src/locales/zh.json
index b9f6e5f08..f2d4a2f6a 100644
--- a/src/locales/zh.json
+++ b/src/locales/zh.json
@@ -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 藏品",
diff --git a/src/models/UDT/index.ts b/src/models/UDT/index.ts
index 489fba58c..ba47afadd 100644
--- a/src/models/UDT/index.ts
+++ b/src/models/UDT/index.ts
@@ -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 {
diff --git a/src/pages/ExportTransactions/index.tsx b/src/pages/ExportTransactions/index.tsx
index cc07a4f5b..3d12d77a2 100644
--- a/src/pages/ExportTransactions/index.tsx
+++ b/src/pages/ExportTransactions/index.tsx
@@ -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'
@@ -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)
diff --git a/src/pages/Tokens/index.tsx b/src/pages/Tokens/index.tsx
index a9f54aa51..e64d1a9ae 100644
--- a/src/pages/Tokens/index.tsx
+++ b/src/pages/Tokens/index.tsx
@@ -95,7 +95,9 @@ const TokenItem = ({ token, isLast }: { token: UDT | OmigaInscriptionCollection;
{symbol}
diff --git a/src/pages/UDT/UDTComp.tsx b/src/pages/UDT/UDTComp.tsx
index 78ee536c0..f09a08577 100644
--- a/src/pages/UDT/UDTComp.tsx
+++ b/src/pages/UDT/UDTComp.tsx
@@ -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'
@@ -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) {
@@ -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 ? (
+
+
+
+
+
+ ) : null,
+ ]}
rightContent={!isMobile && modifyTokenInfo}
/>
@@ -189,6 +204,7 @@ export const UDTComp = ({
filterNoResult,
id,
isInscription,
+ isViewOriginal,
}: {
currentPage: number
pageSize: number
@@ -198,6 +214,7 @@ export const UDTComp = ({
filterNoResult?: boolean
id: string
isInscription?: boolean
+ isViewOriginal?: boolean
}) => {
const { t } = useTranslation()
const totalPages = Math.ceil(total / pageSize)
@@ -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 && }
+ rear={
+
+ }
/>
>
diff --git a/src/pages/UDT/index.tsx b/src/pages/UDT/index.tsx
index 7cf1efc5b..ee90c3902 100644
--- a/src/pages/UDT/index.tsx
+++ b/src/pages/UDT/index.tsx
@@ -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) => ({
@@ -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 (
@@ -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 }))}
/>
-
-
- {filterList.map(f => (
-
- {f.title}
-
-
- ))}
-
- }
- >
-
-
-
@@ -154,6 +106,7 @@ export const UDT: FC<{ isInscription?: boolean }> = ({ isInscription }) => {
filterNoResult={filterNoResult}
id={typeHash}
isInscription={isInscription}
+ isViewOriginal={isViewOriginal}
/>
)}
diff --git a/src/pages/UDT/state.ts b/src/pages/UDT/state.ts
index 31bbb2fe5..a6eb417bd 100644
--- a/src/pages/UDT/state.ts
+++ b/src/pages/UDT/state.ts
@@ -27,4 +27,5 @@ export const defaultOmigaInscriptionInfo: OmigaInscriptionCollection = {
mintLimit: '0',
expectedSupply: '0',
inscriptionInfoId: '',
+ infoTypeHash: '',
}
diff --git a/src/pages/UDT/styles.module.scss b/src/pages/UDT/styles.module.scss
index 3c9a02ff8..e1d0da3c6 100644
--- a/src/pages/UDT/styles.module.scss
+++ b/src/pages/UDT/styles.module.scss
@@ -68,6 +68,17 @@
}
}
+.viewOriginal {
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: 100%;
+
+ &:hover {
+ color: var(--primary-color);
+ }
+}
+
.addressWidthModify {
max-width: 80%;
@@ -92,63 +103,3 @@
width: 100%;
}
}
-
-.typeFilter {
- // hide the filter icon until the api is ready
- display: none;
- cursor: pointer;
- padding-left: 0.8rem;
-
- svg {
- color: #999;
- }
-
- &[data-is-active='true'] {
- svg {
- color: var(--primary-color);
- }
- }
-}
-
-.filterItems {
- display: flex;
- flex-direction: column;
- width: 200px;
-
- a {
- display: flex;
- justify-content: space-between;
- color: var(--primary-color);
- padding: 10px 0 10px 10px;
- margin-right: 8px;
- border-radius: 8px;
-
- &:hover {
- background: var(--primary-hover-bg-color);
- color: var(--primary-color);
- cursor: pointer;
- }
-
- &[data-is-active='false'] {
- color: #000;
-
- svg {
- display: none;
- }
- }
- }
-
- svg path {
- fill: var(--primary-color);
- }
-}
-
-.antPopover {
- :global {
- /* stylelint-disable-next-line selector-class-pattern */
- .ant-popover-inner {
- border-radius: 8px;
- box-shadow: 0 2px 10px 0 #eee;
- }
- }
-}
diff --git a/src/pages/UDT/view_original.svg b/src/pages/UDT/view_original.svg
new file mode 100644
index 000000000..492e54de1
--- /dev/null
+++ b/src/pages/UDT/view_original.svg
@@ -0,0 +1,8 @@
+
diff --git a/src/services/ExplorerService/fetcher.ts b/src/services/ExplorerService/fetcher.ts
index 4479c6372..ae27a7bfc 100644
--- a/src/services/ExplorerService/fetcher.ts
+++ b/src/services/ExplorerService/fetcher.ts
@@ -561,13 +561,11 @@ export const apiFetcher = {
page,
size,
filter,
- type,
}: {
typeHash: string
page: number
size: number
filter?: string | null
- type?: string | null
}) =>
v1GetUnwrappedPagedList(`/udt_transactions/${typeHash}`, {
params: {
@@ -575,7 +573,6 @@ export const apiFetcher = {
page_size: size,
address_hash: filter?.startsWith('0x') ? undefined : filter,
tx_hash: filter?.startsWith('0x') ? filter : undefined,
- transfer_action: type,
},
}),
@@ -588,8 +585,10 @@ export const apiFetcher = {
},
}),
- fetchOmigaInscription: (typeHash: string) =>
- v1GetUnwrapped(`/omiga_inscriptions/${typeHash}`),
+ fetchOmigaInscription: (typeHash: string, isViewOriginal: boolean) =>
+ v1GetUnwrapped(
+ `/omiga_inscriptions/${typeHash}${isViewOriginal ? '?status=closed' : ''}`,
+ ),
fetchOmigaInscriptions: (page: number, size: number, sort?: string) =>
v1GetUnwrappedPagedList(`/omiga_inscriptions`, {
@@ -605,11 +604,13 @@ export const apiFetcher = {
id,
date,
block,
+ isViewOriginal,
}: {
type: SupportedExportTransactionType
id?: string
date?: Record<'start' | 'end', Dayjs | undefined>
block?: Record<'from' | 'to', number>
+ isViewOriginal: boolean
}) => {
const rangeParams = {
start_date: date?.start?.valueOf(),
@@ -623,7 +624,9 @@ export const apiFetcher = {
.then(res => toCamelcase(res.data))
}
return requesterV1
- .get(`/${type}/download_csv`, { params: { ...rangeParams, id } })
+ .get(`/${type}/download_csv${isViewOriginal ? '?status=closed' : ''}`, {
+ params: { ...rangeParams, id },
+ })
.then(res => toCamelcase(res.data))
},
diff --git a/src/services/ExplorerService/types.ts b/src/services/ExplorerService/types.ts
index e2b520fea..c85e610b5 100644
--- a/src/services/ExplorerService/types.ts
+++ b/src/services/ExplorerService/types.ts
@@ -208,4 +208,4 @@ interface FetchStatusValue {
// Unused currently
export type FetchStatus = keyof FetchStatusValue
-export type SupportedExportTransactionType = 'address_transactions' | 'blocks' | 'udts' | 'nft'
+export type SupportedExportTransactionType = 'address_transactions' | 'blocks' | 'udts' | 'nft' | 'omiga_inscriptions'
diff --git a/src/utils/object.ts b/src/utils/object.ts
index c0a0928af..d47f209aa 100644
--- a/src/utils/object.ts
+++ b/src/utils/object.ts
@@ -13,3 +13,9 @@ export function omit, U extends keyof T>(obj: T, keys
})
return newObj
}
+
+export function omitNil>(
+ obj: T,
+): { [K in keyof T]: null extends T[K] ? T[K] | undefined : T[K] } {
+ return Object.fromEntries(Object.entries(obj).filter(([, value]) => value != null)) as any
+}