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: add multi-chain transaction history hooks #1233

Merged
merged 52 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 43 commits
Commits
Show all changes
52 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
3c5fe29
init
brtkx Oct 17, 2023
7f98156
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Oct 19, 2023
de37a1f
cleanup
brtkx Oct 19, 2023
e296a9c
clean up
brtkx Oct 19, 2023
c487889
clean up
brtkx Oct 19, 2023
02c35a5
fixes clean ups
brtkx Oct 19, 2023
3b6167c
fixes clean ups
brtkx Oct 19, 2023
f9bf177
clean up
brtkx Oct 19, 2023
186d914
fix build by removing unused files
brtkx Oct 19, 2023
02bb81a
merge master
brtkx Oct 19, 2023
d31d5b9
rename
brtkx Oct 19, 2023
4a8f47c
remove type casting
brtkx Oct 19, 2023
1591093
calc fix
brtkx Oct 19, 2023
1be8c50
page size fix
brtkx Oct 24, 2023
0da51df
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Oct 24, 2023
99489ad
address review comments
brtkx Oct 24, 2023
6f94021
clean up
brtkx Oct 25, 2023
a0778f1
address review comments
brtkx Oct 31, 2023
501e06f
fix key
brtkx Oct 31, 2023
979c5e6
Merge branch 'new-transaction-history-base' of github.com:OffchainLab…
brtkx Nov 21, 2023
ac7cc4f
fix loading
brtkx Nov 21, 2023
d8c0b2e
clean up
brtkx Nov 21, 2023
da9b3a2
rename chain to child chain
brtkx Nov 27, 2023
1813c59
clean up
brtkx Nov 27, 2023
807545c
refactor hooks to only have 2 hooks
brtkx Nov 27, 2023
85c1c5c
make address a prop
brtkx Nov 27, 2023
4f93ba8
move import
brtkx Nov 27, 2023
6a5935a
Merge branch 'master' of github.com:OffchainLabs/arbitrum-token-bridg…
brtkx Nov 29, 2023
b6a5f8f
clean up
brtkx Nov 29, 2023
5d7a48c
throw on missing transaction
brtkx Dec 4, 2023
b1c9b20
user friendly error
brtkx Dec 4, 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
49 changes: 2 additions & 47 deletions packages/arb-token-bridge-ui/src/components/App/AppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,14 @@ type AppContextState = {
isTransferPanelVisible: boolean
isTransferring: boolean
isTransactionHistoryPanelVisible: boolean
isTransactionHistoryShowingCctpDeposits: boolean
transactionHistorySelectedTab: TransactionHistoryTab
}
}

const initialState: AppContextState = {
layout: {
isTransferPanelVisible: true,
isTransferring: false,
isTransactionHistoryPanelVisible: false,
isTransactionHistoryShowingCctpDeposits: true,
transactionHistorySelectedTab: TransactionHistoryTab.DEPOSITS
isTransactionHistoryPanelVisible: false
}
}

Expand All @@ -40,8 +36,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_cctp_deposits'; payload: boolean }
| { type: 'layout.set_txhistory_tab'; payload: TransactionHistoryTab }

function reducer(state: AppContextState, action: Action) {
switch (action.type) {
Expand All @@ -60,30 +54,12 @@ function reducer(state: AppContextState, action: Action) {
}
}

case 'layout.set_txhistory_show_cctp_deposits':
return {
...state,
layout: {
...state.layout,
isTransactionHistoryShowingCctpDeposits: action.payload
}
}

case 'layout.set_is_transferring':
return {
...state,
layout: { ...state.layout, isTransferring: action.payload }
}

case 'layout.set_txhistory_tab':
return {
...state,
layout: {
...state.layout,
transactionHistorySelectedTab: action.payload
}
}

default:
return state
}
Expand Down Expand Up @@ -122,34 +98,13 @@ export const useAppContextActions = (dispatchOverride?: Dispatch<Action>) => {
dispatch({ type: 'layout.set_txhistory_panel_visible', payload: true })
}

const showCctpDepositsTransactions = useCallback(() => {
dispatch({ type: 'layout.set_txhistory_show_cctp_deposits', payload: true })
}, [dispatch])

const showCctpWithdrawalsTransactions = useCallback(() => {
dispatch({
type: 'layout.set_txhistory_show_cctp_deposits',
payload: false
})
}, [dispatch])

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

const setTransactionHistoryTab = useCallback(
(payload: TransactionHistoryTab) => {
dispatch({ type: 'layout.set_txhistory_tab', payload })
},
[dispatch]
)

return {
setTransferring,
openTransactionHistoryPanel,
closeTransactionHistoryPanel,
showCctpDepositsTransactions,
showCctpWithdrawalsTransactions,
setTransactionHistoryTab
closeTransactionHistoryPanel
}
}
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
import { useEffect, useMemo, useState } from 'react'
import { motion, AnimatePresence } from 'framer-motion'
import useLocalStorage from '@rehooks/local-storage'

import { TransferPanel } from '../TransferPanel/TransferPanel'
import { TransactionHistory } from '../TransactionHistory/TransactionHistory'
import { SidePanel } from '../common/SidePanel'
import { useAppContextActions, useAppContextState } from '../App/AppContext'
import { useAppState } from '../../state'
import { useDeposits } from '../../hooks/useDeposits'
import { PageParams } from '../TransactionHistory/TransactionsTable/TransactionsTable'
import { useWithdrawals } from '../../hooks/useWithdrawals'
import { useNetworksAndSigners } from '../../hooks/useNetworksAndSigners'
import { TransactionStatusInfo } from '../TransactionHistory/TransactionStatusInfo'
import { ArbitrumStats, statsLocalStorageKey } from './ArbitrumStats'
import { SettingsDialog } from '../common/SettingsDialog'
import { isNetwork } from '../../util/networks'
import { NewTransactionHistory } from '../NewTransactionHistory/NewTransactionHistory'

export const motionDivProps = {
layout: true,
Expand All @@ -41,70 +33,11 @@ export function MainContent() {
const [isArbitrumStatsVisible] =
useLocalStorage<boolean>(statsLocalStorageKey)

const {
app: { arbTokenBridge }
} = useAppState()

const { l2 } = useNetworksAndSigners()

const [depositsPageParams, setDepositsPageParams] = useState<PageParams>({
searchString: '',
pageNumber: 0,
pageSize: 10
})

const [withdrawalsPageParams, setWithdrawalsPageParams] =
useState<PageParams>({
searchString: '',
pageNumber: 0,
pageSize: 10
})

const pageSize = useMemo(
() => (isNetwork(l2.network.id).isOrbitChain ? 5 : 10),
[l2.network.id]
)

const {
data: depositsData = {
deposits: [],
pendingDeposits: [],
transformedDeposits: []
},
isValidating: depositsLoading,
error: depositsError
} = useDeposits({ ...depositsPageParams, pageSize })

const {
data: withdrawalsData = {
withdrawals: [],
pendingWithdrawals: [],
transformedWithdrawals: []
},
isValidating: withdrawalsLoading,
error: withdrawalsError
} = useWithdrawals({ ...withdrawalsPageParams, pageSize })

useEffect(() => {
// if pending deposits found, add them in the store - this will add them to pending div + start polling for their status
arbTokenBridge?.transactions?.setDepositsInStore?.(
depositsData.pendingDeposits
)
}, [JSON.stringify(depositsData.pendingDeposits)]) // only run side effect on value change, not reference (Call stack exceeded)

useEffect(() => {
// if pending withdrawals found, add them in the store - this will add them to pending div + start polling for their status
arbTokenBridge?.setWithdrawalsInStore?.(withdrawalsData.pendingWithdrawals)
}, [JSON.stringify(withdrawalsData.pendingWithdrawals)]) // only run side effect on value change, not reference (Call stack exceeded)

return (
<div className="flex w-full justify-center">
<div className="main-panel w-full max-w-screen-lg flex-col space-y-6">
<div className="hidden text-center text-5xl">Arbitrum Token Bridge</div>

{/* if the user has some pending claim txns or retryables to redeem, show that banner here */}
<TransactionStatusInfo deposits={depositsData.transformedDeposits} />

<AnimatePresence>
<motion.div
key="transfer-panel"
Expand All @@ -120,21 +53,7 @@ export function MainContent() {
heading="Transaction History"
onClose={closeTransactionHistoryPanel}
>
{/* Transaction history - pending transactions + history table */}
<TransactionHistory
{...{
depositsPageParams: { ...depositsPageParams, pageSize },
withdrawalsPageParams: { ...withdrawalsPageParams, pageSize },
depositsData,
depositsLoading,
depositsError,
withdrawalsData,
withdrawalsLoading,
withdrawalsError,
setDepositsPageParams,
setWithdrawalsPageParams
}}
/>
<NewTransactionHistory />
</SidePanel>

{/* Settings panel */}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// DO NOT REVIEW, THIS WILL CHANGE A LOT WITH THE UI PR
// IT IS ONLY FOR TESTING

import dayjs from 'dayjs'

import { useCompleteMultiChainTransactions } from '../../hooks/useCompleteMultiChainTransactions'
import { DepositStatus, MergedTransaction } from '../../state/app/state'
import { getNetworkName } from '../../util/networks'
import { sanitizeTokenSymbol } from '../../util/TokenUtils'
import { getWagmiChain } from '../../util/wagmi/getWagmiChain'

function isDeposit(tx: MergedTransaction) {
return !tx.isWithdrawal
}

function getSourceChainId(tx: MergedTransaction) {
return isDeposit(tx) ? tx.parentChainId : tx.chainId
}

function getDestChainId(tx: MergedTransaction) {
return isDeposit(tx) ? tx.chainId : tx.parentChainId
}

function getTxStatus(tx: MergedTransaction) {
if (isDeposit(tx)) {
switch (tx.depositStatus) {
case DepositStatus.CREATION_FAILED:
case DepositStatus.L1_FAILURE:
case DepositStatus.L2_FAILURE:
return 'Failure'
case DepositStatus.EXPIRED:
return 'Expired'
case DepositStatus.L1_PENDING:
case DepositStatus.L2_PENDING:
return 'Pending'
default:
return 'Success'
}
} else {
switch (tx.status) {
case 'Executed':
return 'Success'
case 'Confirmed':
return 'Claimable'
case 'Unconfirmed':
return 'Pending'
default:
return 'Failure'
}
}
}

function getRelativeTime(tx: MergedTransaction) {
return dayjs(Number(tx.createdAt)).fromNow()
}

export const NewTransactionHistory = () => {
const {
data: { transactions, total },
loading,
paused
} = useCompleteMultiChainTransactions()

if (loading || transactions.length === 0) {
return <div className="text-white">Fetching transactions...</div>
}

return (
<div className="text-white">
{typeof total === 'number' && transactions.length > 0 && (
<p>
Showing {transactions.length} out of {total} transactions
</p>
)}
<table className="w-full">
<thead>
<th>TIME</th>
<th>TOKEN</th>
<th>FROM</th>
<th>TO</th>
<th>STATUS</th>
<th />
</thead>
<tbody>
{transactions.map(tx => (
<tr key={`${tx.parentChainId}-${tx.chainId}-${tx.txId}`}>
<td>{getRelativeTime(tx)}</td>
<td>
{tx.value}{' '}
{sanitizeTokenSymbol(tx.asset, {
erc20L1Address: tx.tokenAddress,
chain: getWagmiChain(tx.parentChainId)
})}
</td>
<td>{getNetworkName(getSourceChainId(tx))}</td>
<td>{getNetworkName(getDestChainId(tx))}</td>
<td>{getTxStatus(tx)}</td>
</tr>
))}
</tbody>
</table>
</div>
)
}

This file was deleted.

This file was deleted.

Loading