Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: use pagination in transaction inputs/outputs list #188

Closed
wants to merge 12 commits into from
38 changes: 34 additions & 4 deletions src/components/TransactionItem/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactNode, useEffect, useRef } from 'react'
import { ReactNode, useEffect, useRef, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { useQuery } from '@tanstack/react-query'
import RightArrowIcon from './input_arrow_output.png'
import DownArrowIcon from './input_arrow_output_down.png'
import { localeNumberString } from '../../utils/number'
Expand All @@ -11,6 +12,8 @@ import { CellType } from '../../constants/common'
import AddressText from '../AddressText'
import { useIsExtraLarge, useParsedDate } from '../../hooks'
import { Transaction } from '../../models/Transaction'
import { explorerService } from '../../services/ExplorerService'
import Pagination from '../Pagination'

export interface CircleCorner {
top?: boolean
Expand Down Expand Up @@ -75,6 +78,19 @@ const TransactionItem = ({
const isXL = useIsExtraLarge()
const { t } = useTranslation()
const ref = useRef<HTMLDivElement>(null)
const txHash = transaction.transactionHash
// refactor to configurable
Keith-CY marked this conversation as resolved.
Show resolved Hide resolved
const PAGE_SIZE = 10
Keith-CY marked this conversation as resolved.
Show resolved Hide resolved
const [inputCellsPage, setInputCellsPage] = useState(1)
Keith-CY marked this conversation as resolved.
Show resolved Hide resolved
const txInputsQuery = useQuery(['transactionInputs', txHash, inputCellsPage], async () => {
const result = await explorerService.api.fetchTransactionInputsByHash(txHash, inputCellsPage, PAGE_SIZE)
return result
})
const [outputCellsPage, setOutputCellsPage] = useState(1)
const txOutputsQuery = useQuery(['transactionOutputs', txHash, outputCellsPage], async () => {
const result = await explorerService.api.fetchTransactionOutputsByHash(txHash, outputCellsPage, PAGE_SIZE)
return result
})

useEffect(() => {
const el = ref.current
Expand Down Expand Up @@ -108,16 +124,23 @@ const TransactionItem = ({
<TransactionCellPanel>
<div className="transactionItemInput">
<TransactionCellList
cells={transaction.displayInputs}
cells={txInputsQuery.isSuccess ? txInputsQuery.data.data : []}
transaction={transaction}
render={cell => <TransactionCell cell={cell} address={address} cellType={CellType.Input} key={cell.id} />}
/>
{txInputsQuery.isSuccess && txInputsQuery.data.total > PAGE_SIZE && (
<Pagination
currentPage={inputCellsPage}
totalPages={txInputsQuery.isSuccess ? Math.ceil(txInputsQuery.data.total / PAGE_SIZE) : 1}
onChange={setInputCellsPage}
/>
)}
</div>
<img src={isXL ? DownArrowIcon : RightArrowIcon} alt="input and output" />
<div className="transactionItemOutput">
{transaction.displayOutputs && transaction.displayOutputs.length !== 0 ? (
{txOutputsQuery.isSuccess && txOutputsQuery.data.total > 0 ? (
<TransactionCellList
cells={transaction.displayOutputs}
cells={txOutputsQuery.data.data}
transaction={transaction}
render={cell => (
<FullPanel key={cell.id}>
Expand All @@ -128,6 +151,13 @@ const TransactionItem = ({
) : (
<div className="transactionItemOutputEmpty">{t('transaction.empty_output')}</div>
)}
{txOutputsQuery.isSuccess && txOutputsQuery.data.total > PAGE_SIZE && (
<Pagination
currentPage={outputCellsPage}
totalPages={txOutputsQuery.isSuccess ? Math.ceil(txOutputsQuery.data.total / PAGE_SIZE) : 1}
onChange={setOutputCellsPage}
/>
)}
</div>
</TransactionCellPanel>
{address && <TransactionIncome income={transaction.income} />}
Expand Down
52 changes: 48 additions & 4 deletions src/pages/Transaction/TransactionComp/TransactionComp.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { useQuery } from '@tanstack/react-query'
import { useState } from 'react'
import TransactionCellList from '../TransactionCellList'
import { Cell } from '../../../models/Cell'
import { Transaction } from '../../../models/Transaction'
import { explorerService } from '../../../services/ExplorerService'
import Pagination from '../../../components/Pagination'
import Loading from '../../../components/Loading'

const handleCellbaseInputs = (inputs: Cell[], outputs: Cell[]) => {
if (inputs[0] && inputs[0].fromCellbase && outputs[0] && outputs[0].baseReward) {
Expand All @@ -18,18 +23,57 @@ const handleCellbaseInputs = (inputs: Cell[], outputs: Cell[]) => {
}

export const TransactionComp = ({ transaction }: { transaction: Transaction }) => {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the requirements here: #177 (comment)

This component should not be modified to use pagination mode, as it would result in multiple pages making a large number of requests, as seen in #177.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is meant to be changed, I reverted src/components/TransactionItem/index.tsx

const { transactionHash, displayInputs, displayOutputs, blockNumber, isCellbase } = transaction
const txHash = transaction.transactionHash
// refactor to configurable
const PAGE_SIZE = 10
const [inputCellsPage, setInputCellsPage] = useState(1)
const txInputsQuery = useQuery(['transactionInputs', txHash, inputCellsPage], async () => {
Keith-CY marked this conversation as resolved.
Show resolved Hide resolved
const result = await explorerService.api.fetchTransactionInputsByHash(txHash, inputCellsPage, PAGE_SIZE)
return result
})
const [outputCellsPage, setOutputCellsPage] = useState(1)
const txOutputsQuery = useQuery(['transactionOutputs', txHash, outputCellsPage], async () => {
const result = await explorerService.api.fetchTransactionOutputsByHash(txHash, outputCellsPage, PAGE_SIZE)
// TODO: When will displayOutputs be empty? Its type description indicates that it will not be empty.
if (result.data.length > 0) {
result.data[0].isGenesisOutput = transaction.blockNumber === 0
}
return result
})

const { transactionHash, blockNumber, isCellbase } = transaction

const inputs = handleCellbaseInputs(displayInputs, displayOutputs)
const inputs = handleCellbaseInputs(
txInputsQuery.isSuccess ? txInputsQuery.data.data : [],
txOutputsQuery.isSuccess ? txOutputsQuery.data.data : [],
)

/// [0, 11] block doesn't show block reward and only cellbase show block reward
return (
<>
<div className="transactionInputs">
{inputs && <TransactionCellList inputs={inputs} showReward={blockNumber > 0 && isCellbase} />}
{txInputsQuery.isFetching && <Loading show />}
{inputs && <TransactionCellList inputs={inputs} showReward={Number(blockNumber) > 0 && isCellbase} />}
{txInputsQuery.isSuccess && txInputsQuery.data.total > PAGE_SIZE && (
<Pagination
currentPage={inputCellsPage}
totalPages={txInputsQuery.isSuccess ? Math.ceil(txInputsQuery.data.total / PAGE_SIZE) : 1}
onChange={setInputCellsPage}
/>
)}
</div>
<div className="transactionOutputs">
{displayOutputs && <TransactionCellList outputs={displayOutputs} txHash={transactionHash} />}
{txOutputsQuery.isFetching && <Loading show />}
{txOutputsQuery.isSuccess && (
<TransactionCellList outputs={txOutputsQuery.data.data} txHash={transactionHash} />
)}
{txOutputsQuery.isSuccess && txOutputsQuery.data.total > PAGE_SIZE && (
<Pagination
currentPage={outputCellsPage}
totalPages={txOutputsQuery.isSuccess ? Math.ceil(txOutputsQuery.data.total / PAGE_SIZE) : 1}
onChange={setOutputCellsPage}
/>
)}
</div>
</>
)
Expand Down
4 changes: 0 additions & 4 deletions src/pages/Transaction/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ export default () => {

const query = useQuery(['transaction', txHash], async () => {
const transaction = await explorerService.api.fetchTransactionByHash(txHash)
// TODO: When will displayOutputs be empty? Its type description indicates that it will not be empty.
if (transaction.displayOutputs && transaction.displayOutputs.length > 0) {
transaction.displayOutputs[0].isGenesisOutput = transaction.blockNumber === 0
}
return transaction
})
WhiteMinds marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
23 changes: 23 additions & 0 deletions src/services/ExplorerService/fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ const v1GetUnwrappedPagedList = <T>(...args: Parameters<typeof v1GetWrapped>) =>
}
})

const v1GetPagedList = <T>(...args: Parameters<typeof v1GetWrapped>) =>
WhiteMinds marked this conversation as resolved.
Show resolved Hide resolved
v1Get<T[]>(...args).then(res => {
assert(res.meta, 'Unexpected paged list response')
return {
data: res.data,
...res.meta,
}
})

export enum SearchResultType {
Block = 'block',
Transaction = 'ckb_transaction',
Expand Down Expand Up @@ -99,6 +108,20 @@ export const apiFetcher = {
fetchTransactionRaw: (hash: string) => requesterV2.get<unknown>(`transactions/${hash}/raw`).then(res => res.data),

fetchTransactionByHash: (hash: string) => v1GetUnwrapped<Transaction>(`transactions/${hash}`),
WhiteMinds marked this conversation as resolved.
Show resolved Hide resolved
fetchTransactionInputsByHash: (hash: string, page: number, size: number) =>
v1GetPagedList<Cell>(`transactions/${hash}/display_inputs`, {
params: {
page,
page_size: size,
},
}),
fetchTransactionOutputsByHash: (hash: string, page: number, size: number) =>
v1GetPagedList<Cell>(`transactions/${hash}/display_outputs`, {
params: {
page,
page_size: size,
},
}),

fetchTransactionLiteDetailsByHash: (hash: string) =>
requesterV2
Expand Down