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

fix: display sent and received txs in a single table #1167

Merged
merged 29 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
10bcf63
merged withdrawals
brtkx Sep 22, 2023
c83002e
fix event logs and tests
brtkx Sep 25, 2023
505e444
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Sep 25, 2023
4adabd9
nit comment
brtkx Sep 25, 2023
1a20798
fix for scw
brtkx Sep 29, 2023
ff7382a
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Sep 29, 2023
f20bbe1
fix tests
brtkx Oct 2, 2023
e840d6c
clean up
brtkx Oct 2, 2023
5e48957
Merge branch 'master' into or-condition-subgraph
fionnachan Oct 4, 2023
47e3bc1
address comments
brtkx Oct 5, 2023
f825dfd
address comments
brtkx Oct 5, 2023
e0b9240
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Oct 5, 2023
413931b
Merge branch 'or-condition-subgraph' of github.com:OffchainLabs/arbit…
brtkx Oct 5, 2023
35fc325
review changes
brtkx Oct 6, 2023
17d26e3
tsdoc fix
brtkx Oct 6, 2023
54ae273
review comments and clean up
brtkx Oct 10, 2023
1638fc5
revert filters
brtkx Oct 10, 2023
bad1695
clean up
brtkx Oct 10, 2023
40c13ee
move dedupe events
brtkx Oct 10, 2023
86a25d4
sorting
brtkx Oct 10, 2023
241706d
is token withdrawal method
brtkx Oct 10, 2023
c637e43
better types
brtkx Oct 11, 2023
e4de9e7
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Oct 11, 2023
d97d2a3
remove type casting
brtkx Oct 11, 2023
6dfcedb
comments clean up
brtkx Oct 11, 2023
9cd8b14
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Oct 12, 2023
075d571
Merge branch 'master' into or-condition-subgraph
spsjvc Oct 17, 2023
4a17adb
Merge branch 'master' into or-condition-subgraph
fionnachan Oct 18, 2023
b1190f5
Merge branch 'master' into or-condition-subgraph
fionnachan Oct 18, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 2 additions & 24 deletions packages/arb-token-bridge-ui/src/components/App/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ type AppContextState = {
isTransferPanelVisible: boolean
isTransferring: boolean
isTransactionHistoryPanelVisible: boolean
isTransactionHistoryShowingSentTx: boolean
}
}

const initialState: AppContextState = {
layout: {
isTransferPanelVisible: true,
isTransferring: false,
isTransactionHistoryPanelVisible: false,
isTransactionHistoryShowingSentTx: true
isTransactionHistoryPanelVisible: false
}
}

Expand All @@ -27,7 +25,6 @@ type Action =
| { type: 'layout.set_is_transfer_panel_visible'; payload: boolean }
| { type: 'layout.set_is_transferring'; payload: boolean }
| { type: 'layout.set_txhistory_panel_visible'; payload: boolean }
| { type: 'layout.set_txhistory_show_sent_tx'; payload: boolean }

function reducer(state: AppContextState, action: Action) {
switch (action.type) {
Expand All @@ -46,15 +43,6 @@ function reducer(state: AppContextState, action: Action) {
}
}

case 'layout.set_txhistory_show_sent_tx':
return {
...state,
layout: {
...state.layout,
isTransactionHistoryShowingSentTx: action.payload
}
}

case 'layout.set_is_transferring':
return {
...state,
Expand Down Expand Up @@ -99,23 +87,13 @@ export const useAppContextActions = (dispatchOverride?: Dispatch<Action>) => {
dispatch({ type: 'layout.set_txhistory_panel_visible', payload: true })
}

const showSentTransactions = () => {
dispatch({ type: 'layout.set_txhistory_show_sent_tx', payload: true })
}

const showReceivedTransactions = () => {
dispatch({ type: 'layout.set_txhistory_show_sent_tx', payload: false })
}

const closeTransactionHistoryPanel = () => {
dispatch({ type: 'layout.set_txhistory_panel_visible', payload: false })
}

return {
setTransferring,
openTransactionHistoryPanel,
closeTransactionHistoryPanel,
showSentTransactions,
showReceivedTransactions
closeTransactionHistoryPanel
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Tab } from '@headlessui/react'
import { Dispatch, SetStateAction, useEffect, useMemo } from 'react'
import { Dispatch, SetStateAction, useMemo } from 'react'
dewanshparashar marked this conversation as resolved.
Show resolved Hide resolved
import { useAccount, useNetwork } from 'wagmi'
import { twMerge } from 'tailwind-merge'

Expand All @@ -18,7 +18,6 @@ import { isFailed, isPending } from '../../state/app/utils'
import Image from 'next/image'
import { TabButton } from '../common/Tab'
import { useAccountType } from '../../hooks/useAccountType'
import { useAppContextActions } from '../App/AppContext'
import { useCctpFetching, useCctpState } from '../../state/cctpState'
import { MergedTransaction } from '../../state/app/state'
import dayjs from 'dayjs'
Expand Down Expand Up @@ -48,11 +47,8 @@ export const TransactionHistory = ({
setDepositsPageParams: Dispatch<SetStateAction<PageParams>>
setWithdrawalsPageParams: Dispatch<SetStateAction<PageParams>>
}) => {
const { chain } = useNetwork()
const { l1, l2 } = useNetworksAndSigners()
const { isSmartContractWallet } = useAccountType()
const { showSentTransactions, showReceivedTransactions } =
useAppContextActions()
const {
pendingIds: pendingIdsCctp,
transfers: transfersCctp,
Expand Down Expand Up @@ -124,40 +120,6 @@ export const TransactionHistory = ({
const roundedTabClasses =
'roundedTab ui-not-selected:arb-hover relative flex flex-row flex-nowrap items-center gap-0.5 md:gap-2 rounded-tl-lg rounded-tr-lg px-2 md:px-4 py-2 text-base ui-selected:bg-white ui-not-selected:text-white justify-center md:justify-start grow md:grow-0'

function handleSentOrReceivedTxForSCW(index: number) {
if (!isSmartContractWallet || !chain) {
return
}
const isDepositsTab = index === 0
const isConnectedToArbitrum = isNetwork(chain.id).isArbitrum
// SCW address is tied to a specific network, so we must ensure that:
if (isDepositsTab) {
// if showing deposits, we always show:
if (isConnectedToArbitrum) {
// - received txs if connected to L2
showReceivedTransactions()
} else {
// - sent txs if connected to L1
showSentTransactions()
}
} else {
// if showing withdrawals, we always show:
if (isConnectedToArbitrum) {
// - sent txs if connected to L2
showSentTransactions()
} else {
// - received txs if connected to L1
showReceivedTransactions()
}
}
}

useEffect(() => {
// this function runs every time the network tab is changed, and here it is also triggered when the page loads
// it sets the tab to 0 (deposits), which is the default tab
handleSentOrReceivedTxForSCW(0)
}, [isSmartContractWallet, chain])

const displayCctp = transfersIds.length > 0 && !isOrbitChainSelected

return (
Expand All @@ -179,7 +141,7 @@ export const TransactionHistory = ({

{/* Transaction history table */}
<div>
<Tab.Group onChange={handleSentOrReceivedTxForSCW} key={address}>
<Tab.Group key={address}>
<Tab.List className={'flex flex-row whitespace-nowrap'}>
<TabButton
aria-label="show deposit transactions"
Expand Down

This file was deleted.

fionnachan marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@ import { NoDataOverlay } from './NoDataOverlay'
import { TableBodyLoading } from './TableBodyLoading'
import { TableBodyError } from './TableBodyError'
import { TableActionHeader } from './TableActionHeader'
import { TableSentOrReceivedFundsSwitch } from './TableSentOrReceivedFundsSwitch'
import { useAppState } from '../../../state'
import { useAppContextState } from '../../App/AppContext'
import { useNetworksAndSigners } from '../../../hooks/useNetworksAndSigners'
import { ExternalLink } from '../../common/ExternalLink'
import { getExplorerUrl } from '../../../util/networks'
Expand Down Expand Up @@ -183,10 +181,6 @@ export function TransactionsTable({
const {
app: { mergedTransactions: locallyStoredTransactions }
} = useAppState()
const {
layout: { isTransactionHistoryShowingSentTx }
} = useAppContextState()
const { address } = useAccount()

// don't want to update hooks on useAppState reference change. Just the exact value of localTransactions
const localTransactionsKey = JSON.stringify(locallyStoredTransactions || [])
Expand Down Expand Up @@ -235,18 +229,6 @@ export function TransactionsTable({
return [...newerTransactions.reverse(), ...subgraphTransactions]
}, [transactions, localTransactionsKey])
Copy link
Member

Choose a reason for hiding this comment

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

React Hook useMemo has missing dependencies: 'locallyStoredTransactions', 'pageParams.pageNumber', 'pageParams.searchString', and 'type'. Either include them or remove the dependency array.eslintreact-hooks/exhaustive-deps

do we need the other deps?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We haven't had them before but I will have a look.

Maybe @dewanshparashar can have a look as well as I don't believe I've made any changes here before.

Copy link
Contributor

Choose a reason for hiding this comment

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

In dependencies,

  • we don't need locallyStoredTransactions since this state object mutates very frequently and localTransactionsKey (string) is derived from it to keep things under control.
  • pageNumber and searchString can be added, but we only need this memo function to run for the very first page so adding these doesn't make a difference to the logic / result. Just that it will recalculate and do an early return for each update. It's optional.

If we go ahead with it, I'd suggest a different PR to isolate it's impact.

Copy link
Contributor

Choose a reason for hiding this comment

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

we don't need locallyStoredTransactions since this state object mutates very frequently and localTransactionsKey (string) is derived from it to keep things under control.

Then we should either memo it, or not having it as a dependencies, otherwise it make things unpredictable

pageNumber and searchString can be added, but we only need this memo function to run for the very first page so adding these doesn't make a difference to the logic / result. Just that it will recalculate and do an early return for each update. It's optional.

If they are part of the callback of useEffect, then they should be included, even if they never change


const transactionsBySentOrReceivedFunds = useMemo(() => {
if (!address) return []
// both sent and received PENDING txs are stored together
// here we make sure we display a correct tx (sent or received)
return _transactions.filter(tx => {
if (isTransactionHistoryShowingSentTx) {
return tx.sender?.toLowerCase() === address.toLowerCase()
}
return tx.sender?.toLowerCase() !== address.toLowerCase()
})
}, [_transactions, address])

const locallyStoredTransactionsMap = useMemo(() => {
// map of all the locally-stored transactions (pending + recently executed)
// so that tx rows can easily subscribe to live-local status without refetching table data
Expand All @@ -271,14 +253,12 @@ export function TransactionsTable({

return (
<>
{!isSmartContractWallet && <TableSentOrReceivedFundsSwitch />}
chrstph-dvx marked this conversation as resolved.
Show resolved Hide resolved

{/* search and pagination buttons */}
<TableActionHeader
type={type}
pageParams={pageParams}
setPageParams={setPageParams}
transactions={transactionsBySentOrReceivedFunds}
transactions={_transactions}
loading={loading}
showSearch
/>
Expand All @@ -299,7 +279,7 @@ export function TransactionsTable({
{/* when there are no transactions present */}
{status === TableStatus.SUCCESS &&
!noSearchResults &&
!transactionsBySentOrReceivedFunds.length && (
_transactions.length === 0 && (
<EmptyTableRow>
<span className="text-sm font-medium">No transactions</span>
</EmptyTableRow>
Expand All @@ -308,9 +288,8 @@ export function TransactionsTable({
{/* finally, when transactions are present, show rows */}
{status === TableStatus.SUCCESS &&
!noSearchResults &&
transactionsBySentOrReceivedFunds.map((tx, index) => {
const isLastRow =
index === transactionsBySentOrReceivedFunds.length - 1
_transactions.map((tx, index) => {
const isLastRow = index === _transactions.length - 1

// if transaction is present in local (pending + recently executed) transactions, subscribe to that in this row,
// this will make sure the row updates with any updates in the local app state
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type L2ToL1EventResultPlus = L2ToL1EventResult & {

export type WithdrawalInitiated = EventArgs<WithdrawalInitiatedEvent> & {
txHash: string
timestamp?: BigNumber
}

export interface PendingWithdrawalsMap {
Expand Down
45 changes: 31 additions & 14 deletions packages/arb-token-bridge-ui/src/hooks/useDeposits.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { useMemo } from 'react'
import useSWRImmutable from 'swr/immutable'
import { useAccount } from 'wagmi'
import { useAccount, useChainId } from 'wagmi'

import { PageParams } from '../components/TransactionHistory/TransactionsTable/TransactionsTable'
import { useAppContextState } from '../components/App/AppContext'
import { MergedTransaction } from '../state/app/state'
import { isPending, transformDeposits } from '../state/app/utils'
import {
Expand All @@ -12,9 +11,10 @@ import {
} from '../util/deposits/fetchDeposits'
import { useNetworksAndSigners } from './useNetworksAndSigners'
import { Transaction } from './useTransactions'
import { useAccountType } from './useAccountType'
import {
getQueryParamsForFetchingReceivedFunds,
getQueryParamsForFetchingSentFunds
shouldIncludeSentTxs,
shouldIncludeReceivedTxs
} from '../util/SubgraphUtils'

export type CompleteDepositData = {
Expand Down Expand Up @@ -46,16 +46,35 @@ export const fetchCompleteDepositData = async (

export const useDeposits = (depositPageParams: PageParams) => {
const { l1, l2 } = useNetworksAndSigners()
const { isSmartContractWallet, isLoading: isAccountTypeLoading } =
useAccountType()
const chainId = useChainId()

const isConnectedToParentChain = l1.network.id === chainId

// only change l1-l2 providers (and hence, reload deposits) when the connected chain id changes
// otherwise tx-history unnecessarily reloads on l1<->l2 network switch as well (#847)
const l1Provider = useMemo(() => l1.provider, [l1.network.id])
const l2Provider = useMemo(() => l2.provider, [l2.network.id])

const { address: walletAddress } = useAccount()
const {
layout: { isTransactionHistoryShowingSentTx }
} = useAppContextState()

// sent and received txs are always displayed for EOA but not for SCW
fionnachan marked this conversation as resolved.
Show resolved Hide resolved
const includeSentTxs = isAccountTypeLoading
? false
: shouldIncludeSentTxs({
type: 'deposit',
isSmartContractWallet,
isConnectedToParentChain
})

const includeReceivedTxs = isAccountTypeLoading
? false
: shouldIncludeReceivedTxs({
type: 'deposit',
isSmartContractWallet,
isConnectedToParentChain
})

/* return the cached response for the complete pending transactions */
return useSWRImmutable(
Expand All @@ -65,31 +84,29 @@ export const useDeposits = (depositPageParams: PageParams) => {
walletAddress,
l1Provider,
l2Provider,
isTransactionHistoryShowingSentTx,
depositPageParams.pageNumber,
depositPageParams.pageSize,
depositPageParams.searchString
depositPageParams.searchString,
isAccountTypeLoading
]
: null,
([
,
_walletAddress,
_l1Provider,
_l2Provider,
_isTransactionHistoryShowingSentTx,
_pageNumber,
_pageSize,
_searchString
]) =>
fetchCompleteDepositData({
sender: includeSentTxs ? _walletAddress : undefined,
receiver: includeReceivedTxs ? _walletAddress : undefined,
l1Provider: _l1Provider,
l2Provider: _l2Provider,
pageNumber: _pageNumber,
pageSize: _pageSize,
searchString: _searchString,
...(_isTransactionHistoryShowingSentTx
? getQueryParamsForFetchingSentFunds(_walletAddress)
: getQueryParamsForFetchingReceivedFunds(_walletAddress))
searchString: _searchString
})
)
}
Loading
Loading