Skip to content

Commit 788baa3

Browse files
authored
bug: fix loading transaction history with limit (#60)
1 parent 72dc0e0 commit 788baa3

File tree

15 files changed

+216
-173
lines changed

15 files changed

+216
-173
lines changed
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { LazyLoadDataTable } from '@/features/common/components/lazy-load-data-table'
22
import { Address } from '../data/types'
3-
import { useFetchNextAccountTransactionPage } from '../data/account-transaction-history'
4-
import { useCallback } from 'react'
3+
import { createLoadableAccountTransactionsPage } from '../data/account-transaction-history'
4+
import { useCallback, useMemo } from 'react'
55
import { getAccountTransactionsTableSubRows } from '../utils/get-account-transactions-table-sub-rows'
66
import { InnerTransaction, Transaction } from '@/features/transactions/models'
77
import { transactionsTableColumns } from '@/features/transactions/components/transactions-table-columns'
@@ -11,8 +11,8 @@ type Props = {
1111
}
1212

1313
export function AccountTransactionHistory({ address }: Props) {
14-
const fetchNextPage = useFetchNextAccountTransactionPage(address)
14+
const createLoadablePage = useMemo(() => createLoadableAccountTransactionsPage(address), [address])
1515
const getSubRows = useCallback((row: Transaction | InnerTransaction) => getAccountTransactionsTableSubRows(address, row), [address])
1616

17-
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} fetchNextPage={fetchNextPage} />
17+
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} createLoadablePage={createLoadablePage} />
1818
}

src/features/accounts/data/account-transaction-history.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { Address } from '../data/types'
22
import { indexer } from '@/features/common/data'
33
import { TransactionResult, TransactionSearchResults } from '@algorandfoundation/algokit-utils/types/indexer'
4-
import { useMemo } from 'react'
5-
import { JotaiStore } from '@/features/common/data/types'
64
import { createTransactionsAtom, transactionResultsAtom } from '@/features/transactions/data'
75
import { atomEffect } from 'jotai-effect'
8-
import { atom, useStore } from 'jotai'
6+
import { atom } from 'jotai'
7+
import { createLoadableViewModelPageAtom } from '@/features/common/data/lazy-load-pagination'
8+
import { DEFAULT_FETCH_SIZE } from '@/features/common/constants'
99

10-
const getAccountTransactionResults = async (address: Address, pageSize: number, nextPageToken?: string) => {
10+
const getAccountTransactionResults = async (address: Address, nextPageToken?: string) => {
1111
const results = (await indexer
1212
.searchForTransactions()
1313
.address(address)
1414
.nextToken(nextPageToken ?? '')
15-
.limit(pageSize)
15+
.limit(DEFAULT_FETCH_SIZE)
1616
.do()) as TransactionSearchResults
1717
return {
1818
transactionResults: results.transactions,
@@ -40,25 +40,28 @@ const createSyncEffect = (transactionResults: TransactionResult[]) => {
4040
})
4141
}
4242

43-
const createAccountTransactionAtom = (store: JotaiStore, address: Address, pageSize: number, nextPageToken?: string) => {
43+
const createAccountTransactionResultsAtom = (address: Address, nextPageToken?: string) => {
4444
return atom(async (get) => {
45-
const { transactionResults, nextPageToken: newNextPageToken } = await getAccountTransactionResults(address, pageSize, nextPageToken)
45+
const { transactionResults, nextPageToken: newNextPageToken } = await getAccountTransactionResults(address, nextPageToken)
4646

4747
get(createSyncEffect(transactionResults))
4848

49-
const transactions = await get(createTransactionsAtom(store, transactionResults))
50-
5149
return {
52-
rows: transactions,
50+
items: transactionResults,
5351
nextPageToken: newNextPageToken,
5452
}
5553
})
5654
}
5755

58-
export const useFetchNextAccountTransactionPage = (address: Address) => {
59-
const store = useStore()
60-
61-
return useMemo(() => {
62-
return (pageSize: number, nextPageToken?: string) => createAccountTransactionAtom(store, address, pageSize, nextPageToken)
63-
}, [store, address])
56+
export const createLoadableAccountTransactionsPage = (address: Address) => {
57+
return createLoadableViewModelPageAtom({
58+
fetchRawData: (nextPageToken?: string) => createAccountTransactionResultsAtom(address, nextPageToken),
59+
createViewModelPageAtom: (store, rawDataPage) =>
60+
atom(async (get) => {
61+
return {
62+
items: await get(createTransactionsAtom(store, rawDataPage.items)),
63+
hasNextPage: rawDataPage.hasNextPage,
64+
}
65+
}),
66+
})
6467
}

src/features/applications/components/application-boxes.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { LazyLoadDataTable } from '@/features/common/components/lazy-load-data-table'
2-
import { useFetchNextApplicationBoxPage } from '../data/application-boxes'
2+
import { createLoadableApplicationBoxesPage } from '../data/application-boxes'
33
import { ApplicationId } from '../data/types'
44
import { ColumnDef } from '@tanstack/react-table'
55
import { ApplicationBoxSummary } from '../models'
@@ -11,10 +11,10 @@ type Props = {
1111
}
1212

1313
export function ApplicationBoxes({ applicationId }: Props) {
14-
const fetchNextPage = useFetchNextApplicationBoxPage(applicationId)
14+
const createLoadablePage = useMemo(() => createLoadableApplicationBoxesPage(applicationId), [applicationId])
1515
const tableColumns = useMemo(() => createTableColumns(applicationId), [applicationId])
1616

17-
return <LazyLoadDataTable columns={tableColumns} fetchNextPage={fetchNextPage} />
17+
return <LazyLoadDataTable columns={tableColumns} createLoadablePage={createLoadablePage} />
1818
}
1919

2020
const createTableColumns = (applicationId: ApplicationId): ColumnDef<ApplicationBoxSummary>[] => [
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { LazyLoadDataTable } from '@/features/common/components/lazy-load-data-table'
22
import { ApplicationId } from '../data/types'
3-
import { useFetchNextApplicationTransactionsPage } from '../data/application-transaction-history'
3+
import { createLoadableApplicationTransactionsPage } from '../data/application-transaction-history'
44
import { InnerTransaction, Transaction } from '@/features/transactions/models'
5-
import { useCallback } from 'react'
5+
import { useCallback, useMemo } from 'react'
66
import { getApplicationTransactionsTableSubRows } from '../utils/get-application-transactions-table-sub-rows'
77
import { transactionsTableColumns } from '@/features/transactions/components/transactions-table-columns'
88

@@ -11,16 +11,17 @@ type Props = {
1111
}
1212

1313
export function ApplicationTransactionHistory({ applicationId }: Props) {
14+
const createLoadablePage = useMemo(() => createLoadableApplicationTransactionsPage(applicationId), [applicationId])
15+
1416
// TODO: for the future
1517
// How we handle getSubRows isn't the best practice. Ideally, we should create a new view model, for example, TransactionForApplication
1618
// and then fetchNextPage should return a list of TransactionForApplication
1719
// TransactionForApplication should be similar to Transaction, but the InnerTransactions should be only transactions that are related to the application
1820
// This way, getSubRows simply return the innerTransactions
19-
const fetchNextPage = useFetchNextApplicationTransactionsPage(applicationId)
2021
const getSubRows = useCallback(
2122
(row: Transaction | InnerTransaction) => getApplicationTransactionsTableSubRows(applicationId, row),
2223
[applicationId]
2324
)
2425

25-
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} fetchNextPage={fetchNextPage} />
26+
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} createLoadablePage={createLoadablePage} />
2627
}

src/features/applications/data/application-boxes.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import { atom, useAtomValue } from 'jotai'
55
import { ApplicationBox, ApplicationBoxSummary } from '../models'
66
import { Buffer } from 'buffer'
77
import { loadable } from 'jotai/utils'
8+
import { createLoadableViewModelPageAtom } from '@/features/common/data/lazy-load-pagination'
9+
import { DEFAULT_FETCH_SIZE } from '@/features/common/constants'
810

9-
const getApplicationBoxes = async (applicationId: ApplicationId, pageSize: number, nextPageToken?: string) => {
11+
const getApplicationBoxes = async (applicationId: ApplicationId, nextPageToken?: string) => {
1012
const results = await indexer
1113
.searchForApplicationBoxes(applicationId)
1214
.nextToken(nextPageToken ?? '')
13-
.limit(pageSize)
15+
.limit(DEFAULT_FETCH_SIZE)
1416
.do()
1517

1618
return {
@@ -22,23 +24,17 @@ const getApplicationBoxes = async (applicationId: ApplicationId, pageSize: numbe
2224
const getApplicationBox = (applicationId: ApplicationId, boxName: string) =>
2325
indexer.lookupApplicationBoxByIDandName(applicationId, Buffer.from(boxName, 'base64')).do()
2426

25-
const createApplicationBoxesAtom = (applicationId: ApplicationId, pageSize: number, nextPageToken?: string) => {
27+
const createApplicationBoxResultsAtom = (applicationId: ApplicationId, nextPageToken?: string) => {
2628
return atom(async () => {
27-
const { boxes, nextPageToken: newNextPageToken } = await getApplicationBoxes(applicationId, pageSize, nextPageToken)
29+
const { boxes, nextPageToken: newNextPageToken } = await getApplicationBoxes(applicationId, nextPageToken)
2830

2931
return {
30-
rows: boxes,
32+
items: boxes,
3133
nextPageToken: newNextPageToken,
3234
}
3335
})
3436
}
3537

36-
export const useFetchNextApplicationBoxPage = (applicationId: ApplicationId) => {
37-
return useMemo(() => {
38-
return (pageSize: number, nextPageToken?: string) => createApplicationBoxesAtom(applicationId, pageSize, nextPageToken)
39-
}, [applicationId])
40-
}
41-
4238
export const useApplicationBox = (applicationId: ApplicationId, boxName: string) => {
4339
return useMemo(() => {
4440
return atom(async () => {
@@ -51,3 +47,10 @@ export const useApplicationBox = (applicationId: ApplicationId, boxName: string)
5147
export const useLoadableApplicationBox = (applicationId: ApplicationId, boxName: string) => {
5248
return useAtomValue(loadable(useApplicationBox(applicationId, boxName)))
5349
}
50+
51+
export const createLoadableApplicationBoxesPage = (applicationId: ApplicationId) => {
52+
return createLoadableViewModelPageAtom({
53+
fetchRawData: (nextPageToken?: string) => createApplicationBoxResultsAtom(applicationId, nextPageToken),
54+
createViewModelPageAtom: (_, rawDataPage) => atom(() => rawDataPage),
55+
})
56+
}
Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { ApplicationId } from './types'
22
import { indexer } from '@/features/common/data'
33
import { TransactionResult, TransactionSearchResults } from '@algorandfoundation/algokit-utils/types/indexer'
4-
import { useMemo } from 'react'
5-
import { JotaiStore } from '@/features/common/data/types'
64
import { createTransactionsAtom, transactionResultsAtom } from '@/features/transactions/data'
75
import { atomEffect } from 'jotai-effect'
8-
import { atom, useStore } from 'jotai'
6+
import { atom } from 'jotai'
7+
import { createLoadableViewModelPageAtom } from '@/features/common/data/lazy-load-pagination'
8+
import { DEFAULT_FETCH_SIZE } from '@/features/common/constants'
99

10-
const getApplicationTransactionResults = async (applicationID: ApplicationId, pageSize: number, nextPageToken?: string) => {
10+
const getApplicationTransactionResults = async (applicationID: ApplicationId, nextPageToken?: string) => {
1111
const results = (await indexer
1212
.searchForTransactions()
1313
.applicationID(applicationID)
1414
.nextToken(nextPageToken ?? '')
15-
.limit(pageSize)
15+
.limit(DEFAULT_FETCH_SIZE)
1616
.do()) as TransactionSearchResults
1717
return {
1818
transactionResults: results.transactions,
@@ -40,29 +40,28 @@ const createSyncEffect = (transactionResults: TransactionResult[]) => {
4040
})
4141
}
4242

43-
const createApplicationTransactionsAtom = (store: JotaiStore, applicationID: ApplicationId, pageSize: number, nextPageToken?: string) => {
43+
const createApplicationTransactionResultsAtom = (applicationID: ApplicationId, nextPageToken?: string) => {
4444
return atom(async (get) => {
45-
const { transactionResults, nextPageToken: newNextPageToken } = await getApplicationTransactionResults(
46-
applicationID,
47-
pageSize,
48-
nextPageToken
49-
)
45+
const { transactionResults, nextPageToken: newNextPageToken } = await getApplicationTransactionResults(applicationID, nextPageToken)
5046

5147
get(createSyncEffect(transactionResults))
5248

53-
const transactions = await get(createTransactionsAtom(store, transactionResults))
54-
5549
return {
56-
rows: transactions,
50+
items: transactionResults,
5751
nextPageToken: newNextPageToken,
5852
}
5953
})
6054
}
6155

62-
export const useFetchNextApplicationTransactionsPage = (applicationID: ApplicationId) => {
63-
const store = useStore()
64-
65-
return useMemo(() => {
66-
return (pageSize: number, nextPageToken?: string) => createApplicationTransactionsAtom(store, applicationID, pageSize, nextPageToken)
67-
}, [store, applicationID])
56+
export const createLoadableApplicationTransactionsPage = (applicationID: ApplicationId) => {
57+
return createLoadableViewModelPageAtom({
58+
fetchRawData: (nextPageToken?: string) => createApplicationTransactionResultsAtom(applicationID, nextPageToken),
59+
createViewModelPageAtom: (store, rawDataPage) =>
60+
atom(async (get) => {
61+
return {
62+
items: await get(createTransactionsAtom(store, rawDataPage.items)),
63+
hasNextPage: rawDataPage.hasNextPage,
64+
}
65+
}),
66+
})
6867
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { LazyLoadDataTable } from '@/features/common/components/lazy-load-data-table'
22
import { AssetId } from '../data/types'
3-
import { useFetchNextAssetTransactionsPage } from '../data/asset-transaction-history'
3+
import { createLoadableAssetTransactionsPage } from '../data/asset-transaction-history'
44
import { Transaction, InnerTransaction } from '@/features/transactions/models'
5-
import { useCallback } from 'react'
5+
import { useCallback, useMemo } from 'react'
66
import { getAssetTransactionsTableSubRows } from '../utils/get-asset-transactions-table-sub-rows'
77
import { transactionsTableColumns } from '@/features/transactions/components/transactions-table-columns'
88

@@ -11,8 +11,8 @@ type Props = {
1111
}
1212

1313
export function AssetTransactionHistory({ assetId }: Props) {
14-
const fetchNextPage = useFetchNextAssetTransactionsPage(assetId)
14+
const createLoadablePage = useMemo(() => createLoadableAssetTransactionsPage(assetId), [assetId])
1515
const getSubRows = useCallback((row: Transaction | InnerTransaction) => getAssetTransactionsTableSubRows(assetId, row), [assetId])
1616

17-
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} fetchNextPage={fetchNextPage} />
17+
return <LazyLoadDataTable columns={transactionsTableColumns} getSubRows={getSubRows} createLoadablePage={createLoadablePage} />
1818
}

src/features/assets/data/asset-transaction-history.ts

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
import { AssetId } from '../data/types'
22
import { indexer } from '@/features/common/data'
33
import { TransactionResult, TransactionSearchResults } from '@algorandfoundation/algokit-utils/types/indexer'
4-
import { useMemo } from 'react'
5-
import { JotaiStore } from '@/features/common/data/types'
64
import { createTransactionsAtom, transactionResultsAtom } from '@/features/transactions/data'
75
import { atomEffect } from 'jotai-effect'
8-
import { atom, useStore } from 'jotai'
6+
import { atom } from 'jotai'
7+
import { createLoadableViewModelPageAtom } from '@/features/common/data/lazy-load-pagination'
8+
import { DEFAULT_FETCH_SIZE } from '@/features/common/constants'
99

10-
const getAssetTransactionResults = async (assetId: AssetId, pageSize: number, nextPageToken?: string) => {
10+
const getAssetTransactionResults = async (assetId: AssetId, nextPageToken?: string) => {
1111
const results = (await indexer
1212
.searchForTransactions()
1313
.assetID(assetId)
1414
.nextToken(nextPageToken ?? '')
15-
.limit(pageSize)
15+
.limit(DEFAULT_FETCH_SIZE)
1616
.do()) as TransactionSearchResults
1717
return {
1818
transactionResults: results.transactions,
@@ -40,25 +40,28 @@ const createSyncEffect = (transactionResults: TransactionResult[]) => {
4040
})
4141
}
4242

43-
const createAssetTransactionsAtom = (store: JotaiStore, assetId: AssetId, pageSize: number, nextPageToken?: string) => {
43+
const createAssetTransactionResultsAtom = (assetId: AssetId, nextPageToken?: string) => {
4444
return atom(async (get) => {
45-
const { transactionResults, nextPageToken: newNextPageToken } = await getAssetTransactionResults(assetId, pageSize, nextPageToken)
45+
const { transactionResults, nextPageToken: newNextPageToken } = await getAssetTransactionResults(assetId, nextPageToken)
4646

4747
get(createSyncEffect(transactionResults))
4848

49-
const transactions = await get(createTransactionsAtom(store, transactionResults))
50-
5149
return {
52-
rows: transactions,
50+
items: transactionResults,
5351
nextPageToken: newNextPageToken,
5452
}
5553
})
5654
}
5755

58-
export const useFetchNextAssetTransactionsPage = (assetId: AssetId) => {
59-
const store = useStore()
60-
61-
return useMemo(() => {
62-
return (pageSize: number, nextPageToken?: string) => createAssetTransactionsAtom(store, assetId, pageSize, nextPageToken)
63-
}, [store, assetId])
56+
export const createLoadableAssetTransactionsPage = (assetId: AssetId) => {
57+
return createLoadableViewModelPageAtom({
58+
fetchRawData: (nextPageToken?: string) => createAssetTransactionResultsAtom(assetId, nextPageToken),
59+
createViewModelPageAtom: (store, rawDataPage) =>
60+
atom(async (get) => {
61+
return {
62+
items: await get(createTransactionsAtom(store, rawDataPage.items)),
63+
hasNextPage: rawDataPage.hasNextPage,
64+
}
65+
}),
66+
})
6467
}

src/features/blocks/data/block.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ const createNextRoundAvailableAtom = (store: JotaiStore, round: Round) => {
2020
const createBlockAtom = (store: JotaiStore, round: Round) => {
2121
return atom(async (get) => {
2222
const blockResult = await get(getBlockResultAtom(store, round))
23-
const transactions = await get(createTransactionsAtom(store, getTransactionResultAtoms(store, blockResult.transactionIds)))
23+
const transactionResults = await Promise.all(getTransactionResultAtoms(store, blockResult.transactionIds).map((txn) => get(txn)))
24+
const transactions = await get(createTransactionsAtom(store, transactionResults))
2425
const nextRoundAvailable = get(createNextRoundAvailableAtom(store, round))
2526
return asBlock(blockResult, transactions, nextRoundAvailable)
2627
})

0 commit comments

Comments
 (0)