From 10bcf634505a1f734d686d58f8390420b6930b43 Mon Sep 17 00:00:00 2001 From: Bartek Date: Fri, 22 Sep 2023 16:49:33 +0200 Subject: [PATCH 01/19] merged withdrawals --- .../src/components/App/AppContext.tsx | 26 +---- .../TransactionHistory/TransactionHistory.tsx | 42 +------ .../TableSentOrReceivedFundsSwitch.tsx | 37 ------ .../TransactionsTable/TransactionsTable.tsx | 33 +----- .../src/hooks/arbTokenBridge.types.ts | 1 + .../src/hooks/useDeposits.ts | 16 +-- .../src/hooks/useWithdrawals.ts | 17 +-- .../src/pages/api/deposits.ts | 43 +++---- .../src/pages/api/withdrawals.ts | 51 ++++---- .../src/util/SubgraphUtils.ts | 24 ---- .../src/util/deposits/fetchDeposits.ts | 17 +-- .../deposits/fetchDepositsFromSubgraph.ts | 15 +-- .../fetchETHWithdrawalsFromEventLogs.ts | 9 +- .../fetchTokenWithdrawalsFromEventLogs.ts | 50 +++++--- .../src/util/withdrawals/fetchWithdrawals.ts | 109 +++++++----------- .../fetchWithdrawalsFromSubgraph.ts | 15 +-- .../src/util/withdrawals/helpers.ts | 36 +++++- 17 files changed, 175 insertions(+), 366 deletions(-) delete mode 100644 packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TableSentOrReceivedFundsSwitch.tsx diff --git a/packages/arb-token-bridge-ui/src/components/App/AppContext.tsx b/packages/arb-token-bridge-ui/src/components/App/AppContext.tsx index 7fbfb4633c..926da4d61f 100644 --- a/packages/arb-token-bridge-ui/src/components/App/AppContext.tsx +++ b/packages/arb-token-bridge-ui/src/components/App/AppContext.tsx @@ -5,7 +5,6 @@ type AppContextState = { isTransferPanelVisible: boolean isTransferring: boolean isTransactionHistoryPanelVisible: boolean - isTransactionHistoryShowingSentTx: boolean } } @@ -13,8 +12,7 @@ const initialState: AppContextState = { layout: { isTransferPanelVisible: true, isTransferring: false, - isTransactionHistoryPanelVisible: false, - isTransactionHistoryShowingSentTx: true + isTransactionHistoryPanelVisible: false } } @@ -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) { @@ -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, @@ -99,14 +87,6 @@ export const useAppContextActions = (dispatchOverride?: Dispatch) => { 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 }) } @@ -114,8 +94,6 @@ export const useAppContextActions = (dispatchOverride?: Dispatch) => { return { setTransferring, openTransactionHistoryPanel, - closeTransactionHistoryPanel, - showSentTransactions, - showReceivedTransactions + closeTransactionHistoryPanel } } diff --git a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx index ab752314a3..e727c5981c 100644 --- a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx @@ -1,5 +1,5 @@ import { Tab } from '@headlessui/react' -import { Dispatch, SetStateAction, useEffect, useMemo } from 'react' +import { Dispatch, SetStateAction, useMemo } from 'react' import { useAccount, useNetwork } from 'wagmi' import { CompleteDepositData } from '../../hooks/useDeposits' @@ -17,7 +17,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' @@ -47,11 +46,8 @@ export const TransactionHistory = ({ setDepositsPageParams: Dispatch> setWithdrawalsPageParams: Dispatch> }) => { - const { chain } = useNetwork() const { l1, l2 } = useNetworksAndSigners() const { isSmartContractWallet } = useAccountType() - const { showSentTransactions, showReceivedTransactions } = - useAppContextActions() const { pendingIds: pendingIdsCctp, transfers: transfersCctp, @@ -123,40 +119,6 @@ export const TransactionHistory = ({ const roundedTabClasses = 'roundedTab ui-not-selected:arb-hover roundedTabRight relative flex flex-row flex-nowrap items-center gap-2 rounded-tl-lg rounded-tr-lg px-4 py-2 text-base ui-selected:bg-white ui-not-selected:text-white' - 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]) - return (
{isNetwork(l2.network.id).isOrbitChain && ( @@ -176,7 +138,7 @@ export const TransactionHistory = ({ {/* Transaction history table */}
- + { - const { - layout: { isTransactionHistoryShowingSentTx } - } = useAppContextState() - const { showSentTransactions, showReceivedTransactions } = - useAppContextActions() - - const tabs = useMemo(() => { - return [ - { - handleClick: showSentTransactions, - text: 'Funds Sent', - isActive: isTransactionHistoryShowingSentTx - }, - { - handleClick: showReceivedTransactions, - text: 'Funds Received', - isActive: !isTransactionHistoryShowingSentTx - } - ] - }, [ - isTransactionHistoryShowingSentTx, - showReceivedTransactions, - showSentTransactions - ]) - - return -} diff --git a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx index 9ccc3821b5..6177c371b6 100644 --- a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx @@ -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' @@ -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 || []) @@ -235,18 +229,6 @@ export function TransactionsTable({ return [...newerTransactions.reverse(), ...subgraphTransactions] }, [transactions, localTransactionsKey]) - 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 @@ -271,18 +253,12 @@ export function TransactionsTable({ return ( <> - {!isSmartContractWallet && ( - - )} - {/* search and pagination buttons */} No transactions @@ -313,9 +289,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 diff --git a/packages/arb-token-bridge-ui/src/hooks/arbTokenBridge.types.ts b/packages/arb-token-bridge-ui/src/hooks/arbTokenBridge.types.ts index 66dfc386a5..19f99fb25e 100644 --- a/packages/arb-token-bridge-ui/src/hooks/arbTokenBridge.types.ts +++ b/packages/arb-token-bridge-ui/src/hooks/arbTokenBridge.types.ts @@ -95,6 +95,7 @@ export type L2ToL1EventResultPlus = L2ToL1EventResult & { export type WithdrawalInitiated = EventArgs & { txHash: string + timestamp?: BigNumber } export interface PendingWithdrawalsMap { diff --git a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts index b2934796b6..d287aa5e9b 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts @@ -3,7 +3,6 @@ import useSWRImmutable from 'swr/immutable' import { useAccount } 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 { @@ -12,10 +11,6 @@ import { } from '../util/deposits/fetchDeposits' import { useNetworksAndSigners } from './useNetworksAndSigners' import { Transaction } from './useTransactions' -import { - getQueryParamsForFetchingReceivedFunds, - getQueryParamsForFetchingSentFunds -} from '../util/SubgraphUtils' export type CompleteDepositData = { deposits: Transaction[] @@ -53,9 +48,6 @@ export const useDeposits = (depositPageParams: PageParams) => { const l2Provider = useMemo(() => l2.provider, [l2.network.id]) const { address: walletAddress } = useAccount() - const { - layout: { isTransactionHistoryShowingSentTx } - } = useAppContextState() /* return the cached response for the complete pending transactions */ return useSWRImmutable( @@ -65,7 +57,6 @@ export const useDeposits = (depositPageParams: PageParams) => { walletAddress, l1Provider, l2Provider, - isTransactionHistoryShowingSentTx, depositPageParams.pageNumber, depositPageParams.pageSize, depositPageParams.searchString @@ -76,20 +67,17 @@ export const useDeposits = (depositPageParams: PageParams) => { _walletAddress, _l1Provider, _l2Provider, - _isTransactionHistoryShowingSentTx, _pageNumber, _pageSize, _searchString ]) => fetchCompleteDepositData({ + address: _walletAddress, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, pageSize: _pageSize, - searchString: _searchString, - ...(_isTransactionHistoryShowingSentTx - ? getQueryParamsForFetchingSentFunds(_walletAddress) - : getQueryParamsForFetchingReceivedFunds(_walletAddress)) + searchString: _searchString }) ) } diff --git a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts index abdd820816..d57003f4a0 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts @@ -11,11 +11,6 @@ import { } from '../util/withdrawals/fetchWithdrawals' import { L2ToL1EventResultPlus } from './arbTokenBridge.types' import { useNetworksAndSigners } from './useNetworksAndSigners' -import { useAppContextState } from '../components/App/AppContext' -import { - getQueryParamsForFetchingReceivedFunds, - getQueryParamsForFetchingSentFunds -} from '../util/SubgraphUtils' export type CompleteWithdrawalData = { withdrawals: L2ToL1EventResultPlus[] @@ -61,10 +56,6 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { const l1Provider = useMemo(() => l1.provider, [l1.network.id]) const l2Provider = useMemo(() => l2.provider, [l2.network.id]) - const { - layout: { isTransactionHistoryShowingSentTx } - } = useAppContextState() - const { address: walletAddress } = useAccount() /* return the cached response for the complete pending transactions */ @@ -77,7 +68,6 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { walletAddress, l1Provider, l2Provider, - isTransactionHistoryShowingSentTx, withdrawalPageParams.pageNumber, withdrawalPageParams.pageSize, withdrawalPageParams.searchString @@ -88,20 +78,17 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { _walletAddress, _l1Provider, _l2Provider, - _isTransactionHistoryShowingSentTx, _pageNumber, _pageSize, _searchString ]) => fetchCompleteWithdrawalData({ + address: _walletAddress, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, pageSize: _pageSize, - searchString: _searchString, - ...(_isTransactionHistoryShowingSentTx - ? getQueryParamsForFetchingSentFunds(_walletAddress) - : getQueryParamsForFetchingReceivedFunds(_walletAddress)) + searchString: _searchString }) ) } diff --git a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts index bc5f6dfd28..1bf358a23b 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts @@ -8,10 +8,7 @@ type NextApiRequestWithDepositParams = NextApiRequest & { query: { l2ChainId: string search?: string - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address?: string page?: string pageSize?: string fromBlock?: string @@ -32,10 +29,7 @@ export default async function handler( const { search = '', l2ChainId, - sender, - senderNot, - receiver, - receiverNot, + address, page = '0', pageSize = '10', fromBlock, @@ -53,8 +47,7 @@ export default async function handler( // validate the request parameters const errorMessage = [] if (!l2ChainId) errorMessage.push(' is required') - if (!sender && !receiver) - errorMessage.push(' or is required') + if (!address) errorMessage.push('
is required') if (errorMessage.length) { res.status(400).json({ @@ -67,22 +60,22 @@ export default async function handler( query: gql(`{ deposits( where: { - ${sender ? `sender: "${sender}",` : ''} - ${senderNot ? `sender_not: "${senderNot}",` : ''} - ${receiver ? `receiver: "${receiver}",` : ''} - ${receiverNot ? `receiver_not: "${receiverNot}",` : ''} - ${ - typeof fromBlock !== 'undefined' - ? `blockCreatedAt_gte: ${Number(fromBlock)}` - : '' - } - ${ - typeof toBlock !== 'undefined' - ? `blockCreatedAt_lte: ${Number(toBlock)}` - : '' - } - ${search ? `transactionHash_contains: "${search}"` : ''} + or: [ + { sender: "${address}" }, + { receiver: "${address}" } + ] } + ${ + typeof fromBlock !== 'undefined' + ? `blockCreatedAt_gte: ${Number(fromBlock)}` + : '' + } + ${ + typeof toBlock !== 'undefined' + ? `blockCreatedAt_lte: ${Number(toBlock)}` + : '' + } + ${search ? `transactionHash_contains: "${search}"` : ''} orderBy: blockCreatedAt orderDirection: desc first: ${Number(pageSize)}, diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index d11597dcac..3b3e2b109f 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -8,10 +8,7 @@ type NextApiRequestWithWithdrawalParams = NextApiRequest & { query: { l2ChainId: string search?: string - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address: string page?: string pageSize?: string fromBlock?: string @@ -32,10 +29,7 @@ export default async function handler( const { search = '', l2ChainId, - sender, - senderNot, - receiver, - receiverNot, + address, page = '0', pageSize = '10', fromBlock, @@ -53,8 +47,7 @@ export default async function handler( // validate the request parameters const errorMessage = [] if (!l2ChainId) errorMessage.push(' is required') - if (!sender && !receiver) - errorMessage.push(' or is required') + if (!address) errorMessage.push('
is required') if (errorMessage.length) { res.status(400).json({ @@ -66,27 +59,27 @@ export default async function handler( const subgraphResult = await getL2SubgraphClient(Number(l2ChainId)).query({ query: gql`{ withdrawals( - where: { - ${sender ? `sender: "${sender}",` : ''} - ${senderNot ? `sender_not: "${senderNot}",` : ''} - ${receiver ? `receiver: "${receiver}",` : ''} - ${receiverNot ? `receiver_not: "${receiverNot}",` : ''} + where: { + or: [ + { sender: "${address}" }, + { receiver: "${address}" } + ] + } + ${ + typeof fromBlock !== 'undefined' + ? `l2BlockNum_gte: ${Number(fromBlock)}` + : '' + } ${ - typeof fromBlock !== 'undefined' - ? `l2BlockNum_gte: ${Number(fromBlock)}` + typeof toBlock !== 'undefined' + ? `l2BlockNum_lte: ${Number(toBlock)}` : '' - } - ${ - typeof toBlock !== 'undefined' - ? `l2BlockNum_lte: ${Number(toBlock)}` - : '' - } - ${search ? `l2TxHash_contains: "${search}"` : ''} - } - orderBy: l2BlockTimestamp - orderDirection: desc - first: ${Number(pageSize)}, - skip: ${Number(page) * Number(pageSize)} + } + ${search ? `l2TxHash_contains: "${search}"` : ''} + orderBy: l2BlockTimestamp + orderDirection: desc + first: ${Number(pageSize)}, + skip: ${Number(page) * Number(pageSize)} ) { id, type, diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index 38fe544e83..fca64e0d18 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -1,7 +1,5 @@ import fetch from 'cross-fetch' import { ApolloClient, HttpLink, InMemoryCache, gql } from '@apollo/client' -import { FetchDepositParams } from './deposits/fetchDeposits' -import { FetchWithdrawalsParams } from './withdrawals/fetchWithdrawals' const L1SubgraphClient = { ArbitrumOne: new ApolloClient({ @@ -120,25 +118,3 @@ export const tryFetchLatestSubgraphBlockNumber = async ( return 0 } } - -type AdditionalSubgraphQueryParams = Pick< - FetchDepositParams | FetchWithdrawalsParams, - 'sender' | 'senderNot' | 'receiver' | 'receiverNot' -> - -export function getQueryParamsForFetchingSentFunds( - address: string -): AdditionalSubgraphQueryParams { - return { - sender: address - } -} - -export function getQueryParamsForFetchingReceivedFunds( - address: string -): AdditionalSubgraphQueryParams { - return { - senderNot: address, - receiver: address - } -} diff --git a/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts b/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts index 51a616970f..68b4474363 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts @@ -10,10 +10,7 @@ import { AssetType } from '../../hooks/arbTokenBridge.types' import { Transaction } from '../../hooks/useTransactions' export type FetchDepositParams = { - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address: string fromBlock?: number toBlock?: number l1Provider: Provider @@ -27,10 +24,7 @@ export type FetchDepositParams = { /* Also fills in any additional data required per transaction for our UI logic to work well */ /* TODO : Add event logs as well */ export const fetchDeposits = async ({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l1Provider, @@ -39,7 +33,7 @@ export const fetchDeposits = async ({ pageNumber = 0, searchString = '' }: FetchDepositParams): Promise => { - if (!sender && !receiver) return [] + if (!address) return [] if (!l1Provider || !l2Provider) return [] const l1ChainId = (await l1Provider.getNetwork()).chainId @@ -67,10 +61,7 @@ export const fetchDeposits = async ({ } const depositsFromSubgraph = await fetchDepositsFromSubgraph({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l2ChainId, diff --git a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts index ce767f7bb6..1da5dd1334 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts @@ -35,10 +35,7 @@ export type FetchDepositsFromSubgraphResult = { */ export const fetchDepositsFromSubgraph = async ({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l2ChainId, @@ -46,10 +43,7 @@ export const fetchDepositsFromSubgraph = async ({ pageNumber = 0, searchString = '' }: { - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address: string fromBlock: number toBlock: number l2ChainId: number @@ -64,10 +58,7 @@ export const fetchDepositsFromSubgraph = async ({ const urlParams = new URLSearchParams( sanitizeQueryParams({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l2ChainId, diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts index 6d1db68015..397d3e71ad 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts @@ -10,21 +10,22 @@ import { L2ToL1MessageReader } from '@arbitrum/sdk' * @param query.toBlock Stop at this block number (including) * @param query.l2Provider Provider for the L2 network */ -export function fetchETHWithdrawalsFromEventLogs({ - toAddress, +export async function fetchETHWithdrawalsFromEventLogs({ + address, fromBlock, toBlock, l2Provider }: { - toAddress?: string + address?: string fromBlock: BlockTag toBlock: BlockTag l2Provider: Provider }) { + // gets txs to the same address return L2ToL1MessageReader.getL2ToL1Events( l2Provider, { fromBlock, toBlock }, undefined, - toAddress + address ) } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index e40ae53d91..2d8003bdd3 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -5,23 +5,20 @@ import { Erc20Bridger } from '@arbitrum/sdk' * Fetches initiated token withdrawals from event logs in range of [fromBlock, toBlock]. * * @param query Query params - * @param query.fromAddress Address that initiated the withdrawal - * @param query.toAddress Address that will receive the funds + * @param query.address Address that initiated the withdrawal, or received the funds * @param query.fromBlock Start at this block number (including) * @param query.toBlock Stop at this block number (including) * @param query.l2Provider Provider for the L2 network * @param query.l2GatewayAddresses L2 gateway addresses to use */ export async function fetchTokenWithdrawalsFromEventLogs({ - fromAddress, - toAddress, + address, fromBlock, toBlock, l2Provider, l2GatewayAddresses = [] }: { - fromAddress?: string - toAddress?: string + address: string fromBlock: BlockTag toBlock: BlockTag l2Provider: Provider @@ -29,18 +26,35 @@ export async function fetchTokenWithdrawalsFromEventLogs({ }) { const erc20Bridger = await Erc20Bridger.fromProvider(l2Provider) + const promises = l2GatewayAddresses.flatMap(gatewayAddress => [ + // funds sent by this address + erc20Bridger.getL2WithdrawalEvents( + l2Provider, + gatewayAddress, + { fromBlock, toBlock }, + undefined, + address, + undefined + ), + // funds received by this address + erc20Bridger.getL2WithdrawalEvents( + l2Provider, + gatewayAddress, + { fromBlock, toBlock }, + undefined, + undefined, + address + ) + ]) + return ( - await Promise.all( - l2GatewayAddresses.map(gatewayAddress => - erc20Bridger.getL2WithdrawalEvents( - l2Provider, - gatewayAddress, - { fromBlock, toBlock }, - undefined, - fromAddress, - toAddress - ) + (await Promise.all(promises)) + .flat() + // when getting funds received by this address we will also get duplicate txs that are overlapping with the previous query + // we have to filter them out + .filter( + (item, index, self) => + index === self.findIndex(tx => tx.txHash === item.txHash) ) - ) - ).flat() + ) } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index 21c66a6fbb..54f593830a 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -1,9 +1,11 @@ import { Provider } from '@ethersproject/providers' -import { constants as arbitrumConstants } from '@arbitrum/sdk' import { fetchETHWithdrawalsFromEventLogs } from './fetchETHWithdrawalsFromEventLogs' import { + EthWithdrawal, + attachTimestampToTokenWithdrawals, + isEthWithdrawal, mapETHWithdrawalToL2ToL1EventResult, mapTokenWithdrawalFromEventLogsToL2ToL1EventResult, mapWithdrawalToL2ToL1EventResult, @@ -12,14 +14,15 @@ import { import { fetchWithdrawalsFromSubgraph } from './fetchWithdrawalsFromSubgraph' import { tryFetchLatestSubgraphBlockNumber } from '../SubgraphUtils' import { fetchTokenWithdrawalsFromEventLogs } from './fetchTokenWithdrawalsFromEventLogs' -import { L2ToL1EventResultPlus } from '../../hooks/arbTokenBridge.types' +import { + L2ToL1EventResultPlus, + WithdrawalInitiated +} from '../../hooks/arbTokenBridge.types' import { fetchL2Gateways } from '../fetchL2Gateways' +import { constants } from 'ethers' export type FetchWithdrawalsParams = { - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address: string fromBlock?: number toBlock?: number l1Provider: Provider @@ -32,10 +35,7 @@ export type FetchWithdrawalsParams = { /* Fetch complete withdrawals - both ETH and Token withdrawals from subgraph and event logs into one list */ /* Also fills in any additional data required per transaction for our UI logic to work well */ export const fetchWithdrawals = async ({ - sender, - senderNot, - receiver, - receiverNot, + address, l1Provider, l2Provider, pageNumber = 0, @@ -44,7 +44,7 @@ export const fetchWithdrawals = async ({ fromBlock, toBlock }: FetchWithdrawalsParams) => { - if (typeof sender === 'undefined' && typeof receiver === 'undefined') { + if (typeof address === 'undefined') { return [] } @@ -68,41 +68,13 @@ export const fetchWithdrawals = async ({ toBlock = latestSubgraphBlockNumber } - // todo: update when eth withdrawals to a custom destination address are enabled (requires https://github.com/OffchainLabs/arbitrum-sdk/issues/325) - function getETHWithdrawalsFromEventLogsQuery() { - // give me all the eth withdrawals that someone else initiated, but the funds are sent to me - if (receiver) { - // since we don't do eth withdrawals to a custom destination address, we don't expect any results here - // however, if we pass in `undefined`, it will skip the filter and give us everything, which is why we use the node interface address that should never return any results - return { toAddress: arbitrumConstants.NODE_INTERFACE_ADDRESS } - } - - // give me all the eth withdrawals that i initiated - // since we don't do eth withdrawals to a custom destination address, we set `toAddress` to be the sender, giving us all withdrawals sent to the same address - return { toAddress: sender } - } - - function getTokenWithdrawalsFromEventLogsQuery() { - // give me all the token withdrawals that someone else initiated, but the funds are sent to me - // because we can't exclude withdrawals that were sent from the same address, we have to filter them out later, see `mappedTokenWithdrawalsFromEventLogs` - if (receiver) { - return { fromAddress: undefined, toAddress: receiver } - } - - // give me all the token withdrawals that i initiated - return { fromAddress: sender, toAddress: undefined } - } - const [ withdrawalsFromSubgraph, ethWithdrawalsFromEventLogs, tokenWithdrawalsFromEventLogs ] = await Promise.all([ fetchWithdrawalsFromSubgraph({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock: fromBlock, toBlock: toBlock, l2ChainId: l2ChainID, @@ -111,13 +83,13 @@ export const fetchWithdrawals = async ({ searchString }), fetchETHWithdrawalsFromEventLogs({ - ...getETHWithdrawalsFromEventLogsQuery(), + address, fromBlock: toBlock + 1, toBlock: 'latest', l2Provider: l2Provider }), fetchTokenWithdrawalsFromEventLogs({ - ...getTokenWithdrawalsFromEventLogsQuery(), + address, fromBlock: toBlock + 1, toBlock: 'latest', l2Provider: l2Provider, @@ -129,36 +101,33 @@ export const fetchWithdrawals = async ({ const currentPageStart = pageNumber * pageSize const currentPageEnd = currentPageStart + pageSize - const partialEthWithdrawalsFromEventLogs = [...ethWithdrawalsFromEventLogs] - // event logs start from the earliest, we need to reverse them - .reverse() - .slice(currentPageStart, currentPageEnd) - const partialTokenWithdrawalsFromEventLogs = [ - ...tokenWithdrawalsFromEventLogs + // we need timestamps to sort token withdrawals along ETH withdrawals + const tokenWithdrawalsFromEventLogsWithTimestamp = + await attachTimestampToTokenWithdrawals({ + withdrawals: tokenWithdrawalsFromEventLogs, + l2Provider + }) + + // get ETH and token withdrawals that will be displayed on the current page + const partialWithdrawalsFromEventLogs = [ + ...ethWithdrawalsFromEventLogs, + ...tokenWithdrawalsFromEventLogsWithTimestamp ] - .reverse() + .sort((a, b) => (a.timestamp?.gt(b.timestamp || constants.Zero) ? -1 : 1)) .slice(currentPageStart, currentPageEnd) - const mappedTokenWithdrawalsFromEventLogs = ( - await Promise.all( - partialTokenWithdrawalsFromEventLogs.map(withdrawal => + const mappedTokenWithdrawalsFromEventLogs = await Promise.all( + partialWithdrawalsFromEventLogs + .filter(withdrawal => !isEthWithdrawal(withdrawal)) + .map(withdrawal => mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( - withdrawal, + withdrawal as WithdrawalInitiated, l1Provider, l2Provider, l2ChainID ) ) - ) ) - // when viewing received funds, we don't want to see funds sent from the same address, so we filter them out - .filter(withdrawal => { - if (senderNot && receiver && withdrawal) { - return withdrawal.sender?.toLowerCase() !== senderNot.toLowerCase() - } - - return true - }) const l2ToL1Txns = [ ...(await Promise.all([ @@ -170,14 +139,16 @@ export const fetchWithdrawals = async ({ l2ChainID ) ), - ...partialEthWithdrawalsFromEventLogs.map(withdrawal => - mapETHWithdrawalToL2ToL1EventResult( - withdrawal, - l1Provider, - l2Provider, - l2ChainID + ...partialWithdrawalsFromEventLogs + .filter(isEthWithdrawal) + .map(withdrawal => + mapETHWithdrawalToL2ToL1EventResult( + withdrawal as EthWithdrawal, + l1Provider, + l2Provider, + l2ChainID + ) ) - ) ])), ...mappedTokenWithdrawalsFromEventLogs ] diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts index 2ed36eb318..1bb2adf8b5 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts @@ -29,10 +29,7 @@ export type FetchWithdrawalsFromSubgraphResult = { * @param query.searchString Searches records through the l2TxHash */ export async function fetchWithdrawalsFromSubgraph({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l2ChainId, @@ -40,10 +37,7 @@ export async function fetchWithdrawalsFromSubgraph({ pageNumber = 0, searchString = '' }: { - sender?: string - senderNot?: string - receiver?: string - receiverNot?: string + address: string fromBlock: number toBlock: number l2ChainId: number @@ -58,10 +52,7 @@ export async function fetchWithdrawalsFromSubgraph({ const urlParams = new URLSearchParams( sanitizeQueryParams({ - sender, - senderNot, - receiver, - receiverNot, + address, fromBlock, toBlock, l2ChainId, diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index 77b3bfe7a7..8eeb06dadd 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -15,6 +15,11 @@ import { } from '../../hooks/arbTokenBridge.types' import { getExecutedMessagesCacheKey } from '../../hooks/useArbTokenBridge' +export type EthWithdrawal = L2ToL1EventResult & { + l2TxHash?: string + transactionHash?: string +} + export const updateAdditionalWithdrawalData = async ( withdrawalTx: L2ToL1EventResultPlus, l1Provider: Provider, @@ -29,10 +34,33 @@ export const updateAdditionalWithdrawalData = async ( return l2toL1TxWithDeadline } +export async function attachTimestampToTokenWithdrawals({ + withdrawals, + l2Provider +}: { + withdrawals: WithdrawalInitiated[] + l2Provider: Provider +}) { + return Promise.all( + [...withdrawals].map(async withdrawal => { + const txReceipt = await l2Provider.getTransactionReceipt( + withdrawal.txHash + ) + const l2TxReceipt = new L2TransactionReceipt(txReceipt) + const [event] = l2TxReceipt.getL2ToL1Events() + + return { + ...withdrawal, + timestamp: event?.timestamp + } + }) + ) +} + export async function mapETHWithdrawalToL2ToL1EventResult( // `l2TxHash` exists on result from subgraph // `transactionHash` exists on result from event logs - event: L2ToL1EventResult & { l2TxHash?: string; transactionHash?: string }, + event: EthWithdrawal, l1Provider: Provider, l2Provider: Provider, l2ChainId: number @@ -134,6 +162,12 @@ export async function attachNodeBlockDeadlineToEvent( } } +export function isEthWithdrawal( + withdrawal: WithdrawalInitiated | EthWithdrawal +): withdrawal is EthWithdrawal { + return typeof (withdrawal as EthWithdrawal).ethBlockNum !== 'undefined' +} + export async function mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( result: WithdrawalInitiated, l1Provider: Provider, From c83002e983e08b66c73c1de1e18cc2d455abc260 Mon Sep 17 00:00:00 2001 From: Bartek Date: Mon, 25 Sep 2023 13:09:06 +0200 Subject: [PATCH 02/19] fix event logs and tests --- .../src/pages/api/deposits.ts | 28 ++++++++++--------- .../src/pages/api/withdrawals.ts | 28 ++++++++++--------- .../__tests__/fetchDepositsTestHelpers.ts | 4 +-- .../fetchETHWithdrawalsTestHelpers.ts | 4 +-- ...fetchTokenWithdrawalsFromEventLogs.test.ts | 12 ++------ .../__tests__/fetchWithdrawalsTestHelpers.ts | 4 +-- .../src/util/withdrawals/fetchWithdrawals.ts | 4 +-- 7 files changed, 41 insertions(+), 43 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts index 1bf358a23b..2372a21fb7 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts @@ -56,26 +56,28 @@ export default async function handler( }) } + const additionalFilters = `${ + typeof fromBlock !== 'undefined' + ? `blockCreatedAt_gte: ${Number(fromBlock)},` + : '' + } + ${ + typeof toBlock !== 'undefined' + ? `blockCreatedAt_lte: ${Number(toBlock)},` + : '' + } + ${search ? `transactionHash_contains: "${search}"` : ''} + ` + const subgraphResult = await getL1SubgraphClient(Number(l2ChainId)).query({ query: gql(`{ deposits( where: { or: [ - { sender: "${address}" }, - { receiver: "${address}" } + { sender: "${address}", ${additionalFilters} }, + { receiver: "${address}", ${additionalFilters} } ] } - ${ - typeof fromBlock !== 'undefined' - ? `blockCreatedAt_gte: ${Number(fromBlock)}` - : '' - } - ${ - typeof toBlock !== 'undefined' - ? `blockCreatedAt_lte: ${Number(toBlock)}` - : '' - } - ${search ? `transactionHash_contains: "${search}"` : ''} orderBy: blockCreatedAt orderDirection: desc first: ${Number(pageSize)}, diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index 3b3e2b109f..a2291420f8 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -56,26 +56,28 @@ export default async function handler( }) } + const additionalFilters = `${ + typeof fromBlock !== 'undefined' + ? `l2BlockNum_gte: ${Number(fromBlock)},` + : '' + } + ${ + typeof toBlock !== 'undefined' + ? `l2BlockNum_lte: ${Number(toBlock)},` + : '' + } + ${search ? `l2TxHash_contains: "${search}"` : ''} + ` + const subgraphResult = await getL2SubgraphClient(Number(l2ChainId)).query({ query: gql`{ withdrawals( where: { or: [ - { sender: "${address}" }, - { receiver: "${address}" } + { sender: "${address}", ${additionalFilters} }, + { receiver: "${address}", ${additionalFilters} } ] } - ${ - typeof fromBlock !== 'undefined' - ? `l2BlockNum_gte: ${Number(fromBlock)}` - : '' - } - ${ - typeof toBlock !== 'undefined' - ? `l2BlockNum_lte: ${Number(toBlock)}` - : '' - } - ${search ? `l2TxHash_contains: "${search}"` : ''} orderBy: l2BlockTimestamp orderDirection: desc first: ${Number(pageSize)}, diff --git a/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts index 838231508e..be8d45ffb5 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts @@ -1,7 +1,7 @@ -const sender = '0x5d64a0fd6af0d76a7ed189d4061ffa6823fbf97e' +const address = '0x5d64a0fd6af0d76a7ed189d4061ffa6823fbf97e' const baseQuery = { - sender, + address, l2ChainId: 42161, pageSize: 100 } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts index 5bef08ae95..eb79484e6c 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts @@ -1,10 +1,10 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers' -const toAddress = '0xd898275e8b9428429155752f89fe0899ce232830' +const address = '0xd898275e8b9428429155752f89fe0899ce232830' const l2Provider = new StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc') const baseQuery = { - toAddress, + address, l2Provider } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts index d1c60ca13e..8da04b5b3e 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts @@ -10,10 +10,8 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { // TODO: This is a temporary fix, when Event Logs are enabled for custom address // we will be able to use the same properties, and remove the need to assign sender to address const query = getQueryCoveringClassicOnlyWithoutResults() - const fromAddress = query.sender const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query, - fromAddress + ...query }) expect(result).toHaveLength(0) @@ -21,10 +19,8 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { it('fetches some token withdrawals from event logs pre-nitro', async () => { const query = getQueryCoveringClassicOnlyWithResults() - const fromAddress = query.sender const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query, - fromAddress + ...query }) expect(result).toHaveLength(1) @@ -40,10 +36,8 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { it('fetches some token withdrawals from event logs pre-nitro and post-nitro', async () => { const query = getQueryCoveringClassicAndNitroWithResults() - const fromAddress = query.sender const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query, - fromAddress + ...query }) expect(result).toHaveLength(2) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts index ab941af606..d180407805 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts @@ -1,11 +1,11 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers' -const sender = '0x2Ce910fBba65B454bBAf6A18c952A70f3bcd8299' +const address = '0x2Ce910fBba65B454bBAf6A18c952A70f3bcd8299' const l2Provider = new StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc') const l2ChainId = 42161 const baseQuery = { - sender, + address, l2ChainId, l2Provider, l2GatewayAddresses: [ diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index 54f593830a..ee1505941c 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -75,8 +75,8 @@ export const fetchWithdrawals = async ({ ] = await Promise.all([ fetchWithdrawalsFromSubgraph({ address, - fromBlock: fromBlock, - toBlock: toBlock, + fromBlock, + toBlock, l2ChainId: l2ChainID, pageNumber, pageSize, From 4adabd9d843bb9cf3bca810c0b987845b2aaaef5 Mon Sep 17 00:00:00 2001 From: Bartek Date: Mon, 25 Sep 2023 13:31:58 +0200 Subject: [PATCH 03/19] nit comment --- .../src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index 2d8003bdd3..f572a6c348 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -50,7 +50,7 @@ export async function fetchTokenWithdrawalsFromEventLogs({ return ( (await Promise.all(promises)) .flat() - // when getting funds received by this address we will also get duplicate txs that are overlapping with the previous query + // when getting funds received by this address we will also get duplicate txs returned in 'funds sent by this address' // we have to filter them out .filter( (item, index, self) => From 1a2079834290ac1f8b49eec3aba372ff12169e56 Mon Sep 17 00:00:00 2001 From: Bartek Date: Fri, 29 Sep 2023 18:37:07 +0200 Subject: [PATCH 04/19] fix for scw --- .../src/hooks/useDeposits.ts | 31 ++++++++++- .../src/hooks/useWithdrawals.ts | 31 ++++++++++- .../src/pages/api/deposits.ts | 17 ++++-- .../src/pages/api/withdrawals.ts | 21 +++++-- .../src/util/SubgraphUtils.ts | 38 +++++++++++++ .../src/util/deposits/fetchDeposits.ts | 12 ++-- .../deposits/fetchDepositsFromSubgraph.ts | 9 ++- .../fetchETHWithdrawalsFromEventLogs.ts | 11 ++-- .../fetchTokenWithdrawalsFromEventLogs.ts | 55 ++++++++++++------- .../src/util/withdrawals/fetchWithdrawals.ts | 16 ++++-- .../fetchWithdrawalsFromSubgraph.ts | 9 ++- 11 files changed, 194 insertions(+), 56 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts index d287aa5e9b..65a08c35cc 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts @@ -1,6 +1,6 @@ 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 { MergedTransaction } from '../state/app/state' @@ -11,6 +11,8 @@ import { } from '../util/deposits/fetchDeposits' import { useNetworksAndSigners } from './useNetworksAndSigners' import { Transaction } from './useTransactions' +import { useAccountType } from './useAccountType' +import { shouldShowReceivedTxs, shouldShowSentTxs } from '../util/SubgraphUtils' export type CompleteDepositData = { deposits: Transaction[] @@ -41,6 +43,11 @@ 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) @@ -49,6 +56,22 @@ export const useDeposits = (depositPageParams: PageParams) => { const { address: walletAddress } = useAccount() + const showSentTxs = isAccountTypeLoading + ? false + : shouldShowSentTxs({ + type: 'deposit', + isSmartContractWallet, + isConnectedToParentChain + }) + + const showReceivedTxs = isAccountTypeLoading + ? false + : shouldShowReceivedTxs({ + type: 'deposit', + isSmartContractWallet, + isConnectedToParentChain + }) + /* return the cached response for the complete pending transactions */ return useSWRImmutable( walletAddress @@ -59,7 +82,8 @@ export const useDeposits = (depositPageParams: PageParams) => { l2Provider, depositPageParams.pageNumber, depositPageParams.pageSize, - depositPageParams.searchString + depositPageParams.searchString, + isAccountTypeLoading ] : null, ([ @@ -72,7 +96,8 @@ export const useDeposits = (depositPageParams: PageParams) => { _searchString ]) => fetchCompleteDepositData({ - address: _walletAddress, + sender: showSentTxs ? _walletAddress : undefined, + receiver: showReceivedTxs ? _walletAddress : undefined, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, diff --git a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts index d57003f4a0..028203555b 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts @@ -1,6 +1,6 @@ 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 { MergedTransaction } from '../state/app/state' @@ -11,6 +11,8 @@ import { } from '../util/withdrawals/fetchWithdrawals' import { L2ToL1EventResultPlus } from './arbTokenBridge.types' import { useNetworksAndSigners } from './useNetworksAndSigners' +import { useAccountType } from './useAccountType' +import { shouldShowReceivedTxs, shouldShowSentTxs } from '../util/SubgraphUtils' export type CompleteWithdrawalData = { withdrawals: L2ToL1EventResultPlus[] @@ -50,6 +52,11 @@ const fetchCompleteWithdrawalData = async ( export const useWithdrawals = (withdrawalPageParams: 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 withdrawals) when the connected chain id changes // otherwise tx-history unnecessarily reloads on l1<->l2 network switch as well (#847) @@ -58,6 +65,22 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { const { address: walletAddress } = useAccount() + const showSentTxs = isAccountTypeLoading + ? false + : shouldShowSentTxs({ + type: 'withdrawal', + isSmartContractWallet, + isConnectedToParentChain + }) + + const showReceivedTxs = isAccountTypeLoading + ? false + : shouldShowReceivedTxs({ + type: 'withdrawal', + isSmartContractWallet, + isConnectedToParentChain + }) + /* return the cached response for the complete pending transactions */ return useSWRImmutable( // `walletAddress` can actually be `undefined`, so the type is wrong @@ -70,7 +93,8 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { l2Provider, withdrawalPageParams.pageNumber, withdrawalPageParams.pageSize, - withdrawalPageParams.searchString + withdrawalPageParams.searchString, + isAccountTypeLoading ] : null, ([ @@ -83,7 +107,8 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { _searchString ]) => fetchCompleteWithdrawalData({ - address: _walletAddress, + sender: showSentTxs ? _walletAddress : undefined, + receiver: showReceivedTxs ? _walletAddress : undefined, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, diff --git a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts index 2372a21fb7..c1dc4124d2 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts @@ -6,9 +6,10 @@ import { getL1SubgraphClient } from '../../util/SubgraphUtils' // Extending the standard NextJs request with Deposit-params type NextApiRequestWithDepositParams = NextApiRequest & { query: { + sender?: string + receiver?: string l2ChainId: string search?: string - address?: string page?: string pageSize?: string fromBlock?: string @@ -27,9 +28,10 @@ export default async function handler( ) { try { const { + sender, + receiver, search = '', l2ChainId, - address, page = '0', pageSize = '10', fromBlock, @@ -47,7 +49,8 @@ export default async function handler( // validate the request parameters const errorMessage = [] if (!l2ChainId) errorMessage.push(' is required') - if (!address) errorMessage.push('
is required') + if (!sender && !receiver) + errorMessage.push(' or is required') if (errorMessage.length) { res.status(400).json({ @@ -74,8 +77,12 @@ export default async function handler( deposits( where: { or: [ - { sender: "${address}", ${additionalFilters} }, - { receiver: "${address}", ${additionalFilters} } + ${sender ? `{ sender: "${sender}", ${additionalFilters} },` : ''} + ${ + receiver + ? `{ receiver: "${receiver}", ${additionalFilters} },` + : '' + } ] } orderBy: blockCreatedAt diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index a2291420f8..16136caf91 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -6,9 +6,10 @@ import { getL2SubgraphClient } from '../../util/SubgraphUtils' // Extending the standard NextJs request with Withdrawal-params type NextApiRequestWithWithdrawalParams = NextApiRequest & { query: { + sender?: string + receiver?: string l2ChainId: string search?: string - address: string page?: string pageSize?: string fromBlock?: string @@ -27,9 +28,10 @@ export default async function handler( ) { try { const { + sender, + receiver, search = '', l2ChainId, - address, page = '0', pageSize = '10', fromBlock, @@ -47,7 +49,8 @@ export default async function handler( // validate the request parameters const errorMessage = [] if (!l2ChainId) errorMessage.push(' is required') - if (!address) errorMessage.push('
is required') + if (!sender && !receiver) + errorMessage.push(' or is required') if (errorMessage.length) { res.status(400).json({ @@ -74,8 +77,16 @@ export default async function handler( withdrawals( where: { or: [ - { sender: "${address}", ${additionalFilters} }, - { receiver: "${address}", ${additionalFilters} } + ${ + sender + ? `{ sender: "${sender}", ${additionalFilters} },` + : '' + } + ${ + receiver + ? `{ receiver: "${receiver}", ${additionalFilters} },` + : '' + } ] } orderBy: l2BlockTimestamp diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index fca64e0d18..5d345779f1 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -118,3 +118,41 @@ export const tryFetchLatestSubgraphBlockNumber = async ( return 0 } } + +export const shouldShowSentTxs = ({ + type, + isSmartContractWallet, + isConnectedToParentChain +}: { + type: 'deposit' | 'withdrawal' + isSmartContractWallet: boolean + isConnectedToParentChain: boolean +}) => { + if (isSmartContractWallet) { + // show txs sent from this account for: + // 1. deposits if we are connected to the parent chain, or + // 2. withdrawals if we are connected to the child chain + return isConnectedToParentChain ? type === 'deposit' : type === 'withdrawal' + } + // always show for EOA + return true +} + +export const shouldShowReceivedTxs = ({ + type, + isSmartContractWallet, + isConnectedToParentChain +}: { + type: 'deposit' | 'withdrawal' + isSmartContractWallet: boolean + isConnectedToParentChain: boolean +}) => { + if (isSmartContractWallet) { + // show txs sent from this account for: + // 1. withdrawals if we are connected to the parent chain, or + // 2. deposits if we are connected to the child chain + return isConnectedToParentChain ? type === 'withdrawal' : type === 'deposit' + } + // always show for EOA + return true +} diff --git a/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts b/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts index 68b4474363..233ebb0a4e 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/fetchDeposits.ts @@ -10,7 +10,8 @@ import { AssetType } from '../../hooks/arbTokenBridge.types' import { Transaction } from '../../hooks/useTransactions' export type FetchDepositParams = { - address: string + sender?: string + receiver?: string fromBlock?: number toBlock?: number l1Provider: Provider @@ -24,7 +25,8 @@ export type FetchDepositParams = { /* Also fills in any additional data required per transaction for our UI logic to work well */ /* TODO : Add event logs as well */ export const fetchDeposits = async ({ - address, + sender, + receiver, fromBlock, toBlock, l1Provider, @@ -33,7 +35,8 @@ export const fetchDeposits = async ({ pageNumber = 0, searchString = '' }: FetchDepositParams): Promise => { - if (!address) return [] + if (typeof sender === 'undefined' && typeof receiver === 'undefined') + return [] if (!l1Provider || !l2Provider) return [] const l1ChainId = (await l1Provider.getNetwork()).chainId @@ -61,7 +64,8 @@ export const fetchDeposits = async ({ } const depositsFromSubgraph = await fetchDepositsFromSubgraph({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId, diff --git a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts index 1da5dd1334..182f7d166d 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts @@ -35,7 +35,8 @@ export type FetchDepositsFromSubgraphResult = { */ export const fetchDepositsFromSubgraph = async ({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId, @@ -43,7 +44,8 @@ export const fetchDepositsFromSubgraph = async ({ pageNumber = 0, searchString = '' }: { - address: string + sender?: string + receiver?: string fromBlock: number toBlock: number l2ChainId: number @@ -58,7 +60,8 @@ export const fetchDepositsFromSubgraph = async ({ const urlParams = new URLSearchParams( sanitizeQueryParams({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId, diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts index 397d3e71ad..696dc343b9 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts @@ -11,21 +11,24 @@ import { L2ToL1MessageReader } from '@arbitrum/sdk' * @param query.l2Provider Provider for the L2 network */ export async function fetchETHWithdrawalsFromEventLogs({ - address, + sender, fromBlock, toBlock, l2Provider }: { - address?: string + sender?: string fromBlock: BlockTag toBlock: BlockTag l2Provider: Provider }) { - // gets txs to the same address + if (typeof sender === 'undefined') { + return [] + } + // funds sent by this address return L2ToL1MessageReader.getL2ToL1Events( l2Provider, { fromBlock, toBlock }, undefined, - address + sender ) } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index f572a6c348..1742ad9b2f 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -12,13 +12,15 @@ import { Erc20Bridger } from '@arbitrum/sdk' * @param query.l2GatewayAddresses L2 gateway addresses to use */ export async function fetchTokenWithdrawalsFromEventLogs({ - address, + sender, + receiver, fromBlock, toBlock, l2Provider, l2GatewayAddresses = [] }: { - address: string + sender?: string + receiver?: string fromBlock: BlockTag toBlock: BlockTag l2Provider: Provider @@ -26,26 +28,39 @@ export async function fetchTokenWithdrawalsFromEventLogs({ }) { const erc20Bridger = await Erc20Bridger.fromProvider(l2Provider) - const promises = l2GatewayAddresses.flatMap(gatewayAddress => [ + const promises = l2GatewayAddresses.flatMap(gatewayAddress => { + const events = [] + // funds sent by this address - erc20Bridger.getL2WithdrawalEvents( - l2Provider, - gatewayAddress, - { fromBlock, toBlock }, - undefined, - address, - undefined - ), + if (sender) { + events.push( + erc20Bridger.getL2WithdrawalEvents( + l2Provider, + gatewayAddress, + { fromBlock, toBlock }, + undefined, + sender, + undefined + ) + ) + } + // funds received by this address - erc20Bridger.getL2WithdrawalEvents( - l2Provider, - gatewayAddress, - { fromBlock, toBlock }, - undefined, - undefined, - address - ) - ]) + if (receiver) { + events.push( + erc20Bridger.getL2WithdrawalEvents( + l2Provider, + gatewayAddress, + { fromBlock, toBlock }, + undefined, + undefined, + receiver + ) + ) + } + + return events + }) return ( (await Promise.all(promises)) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index ee1505941c..ddd1caaaf1 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -22,7 +22,8 @@ import { fetchL2Gateways } from '../fetchL2Gateways' import { constants } from 'ethers' export type FetchWithdrawalsParams = { - address: string + sender?: string + receiver?: string fromBlock?: number toBlock?: number l1Provider: Provider @@ -35,7 +36,8 @@ export type FetchWithdrawalsParams = { /* Fetch complete withdrawals - both ETH and Token withdrawals from subgraph and event logs into one list */ /* Also fills in any additional data required per transaction for our UI logic to work well */ export const fetchWithdrawals = async ({ - address, + sender, + receiver, l1Provider, l2Provider, pageNumber = 0, @@ -44,7 +46,7 @@ export const fetchWithdrawals = async ({ fromBlock, toBlock }: FetchWithdrawalsParams) => { - if (typeof address === 'undefined') { + if (typeof sender === 'undefined' && typeof receiver === 'undefined') { return [] } @@ -74,7 +76,8 @@ export const fetchWithdrawals = async ({ tokenWithdrawalsFromEventLogs ] = await Promise.all([ fetchWithdrawalsFromSubgraph({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId: l2ChainID, @@ -83,13 +86,14 @@ export const fetchWithdrawals = async ({ searchString }), fetchETHWithdrawalsFromEventLogs({ - address, + sender, fromBlock: toBlock + 1, toBlock: 'latest', l2Provider: l2Provider }), fetchTokenWithdrawalsFromEventLogs({ - address, + sender, + receiver, fromBlock: toBlock + 1, toBlock: 'latest', l2Provider: l2Provider, diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts index 1bb2adf8b5..13b4972419 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts @@ -29,7 +29,8 @@ export type FetchWithdrawalsFromSubgraphResult = { * @param query.searchString Searches records through the l2TxHash */ export async function fetchWithdrawalsFromSubgraph({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId, @@ -37,7 +38,8 @@ export async function fetchWithdrawalsFromSubgraph({ pageNumber = 0, searchString = '' }: { - address: string + sender?: string + receiver?: string fromBlock: number toBlock: number l2ChainId: number @@ -52,7 +54,8 @@ export async function fetchWithdrawalsFromSubgraph({ const urlParams = new URLSearchParams( sanitizeQueryParams({ - address, + sender, + receiver, fromBlock, toBlock, l2ChainId, From f20bbe13524d1347c127f98f792456993777532a Mon Sep 17 00:00:00 2001 From: Bartek Date: Mon, 2 Oct 2023 12:11:41 +0200 Subject: [PATCH 05/19] fix tests --- .../src/util/deposits/__tests__/fetchDepositsTestHelpers.ts | 4 ++-- .../withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts | 4 ++-- .../util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts index be8d45ffb5..838231508e 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/__tests__/fetchDepositsTestHelpers.ts @@ -1,7 +1,7 @@ -const address = '0x5d64a0fd6af0d76a7ed189d4061ffa6823fbf97e' +const sender = '0x5d64a0fd6af0d76a7ed189d4061ffa6823fbf97e' const baseQuery = { - address, + sender, l2ChainId: 42161, pageSize: 100 } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts index eb79484e6c..9295f467cb 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts @@ -1,10 +1,10 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers' -const address = '0xd898275e8b9428429155752f89fe0899ce232830' +const sender = '0xd898275e8b9428429155752f89fe0899ce232830' const l2Provider = new StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc') const baseQuery = { - address, + sender, l2Provider } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts index d180407805..ab941af606 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchWithdrawalsTestHelpers.ts @@ -1,11 +1,11 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers' -const address = '0x2Ce910fBba65B454bBAf6A18c952A70f3bcd8299' +const sender = '0x2Ce910fBba65B454bBAf6A18c952A70f3bcd8299' const l2Provider = new StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc') const l2ChainId = 42161 const baseQuery = { - address, + sender, l2ChainId, l2Provider, l2GatewayAddresses: [ From e840d6c0b660fab2e756a4fefd1c1ab4243e1c9e Mon Sep 17 00:00:00 2001 From: Bartek Date: Mon, 2 Oct 2023 12:35:14 +0200 Subject: [PATCH 06/19] clean up --- .../src/hooks/useDeposits.ts | 18 +++++++++++------- .../src/hooks/useWithdrawals.ts | 18 +++++++++++------- .../src/util/SubgraphUtils.ts | 4 ++-- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts index 65a08c35cc..6b96c718bc 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts @@ -12,7 +12,10 @@ import { import { useNetworksAndSigners } from './useNetworksAndSigners' import { Transaction } from './useTransactions' import { useAccountType } from './useAccountType' -import { shouldShowReceivedTxs, shouldShowSentTxs } from '../util/SubgraphUtils' +import { + shouldIncludeSentTxs, + shouldIncludeReceivedTxs +} from '../util/SubgraphUtils' export type CompleteDepositData = { deposits: Transaction[] @@ -56,17 +59,18 @@ export const useDeposits = (depositPageParams: PageParams) => { const { address: walletAddress } = useAccount() - const showSentTxs = isAccountTypeLoading + // sent and received txs are always displayed for EOA but not for SCW + const includeSentTxs = isAccountTypeLoading ? false - : shouldShowSentTxs({ + : shouldIncludeSentTxs({ type: 'deposit', isSmartContractWallet, isConnectedToParentChain }) - const showReceivedTxs = isAccountTypeLoading + const includeReceivedTxs = isAccountTypeLoading ? false - : shouldShowReceivedTxs({ + : shouldIncludeReceivedTxs({ type: 'deposit', isSmartContractWallet, isConnectedToParentChain @@ -96,8 +100,8 @@ export const useDeposits = (depositPageParams: PageParams) => { _searchString ]) => fetchCompleteDepositData({ - sender: showSentTxs ? _walletAddress : undefined, - receiver: showReceivedTxs ? _walletAddress : undefined, + sender: includeSentTxs ? _walletAddress : undefined, + receiver: includeReceivedTxs ? _walletAddress : undefined, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, diff --git a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts index 028203555b..7c95648fe0 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts @@ -12,7 +12,10 @@ import { import { L2ToL1EventResultPlus } from './arbTokenBridge.types' import { useNetworksAndSigners } from './useNetworksAndSigners' import { useAccountType } from './useAccountType' -import { shouldShowReceivedTxs, shouldShowSentTxs } from '../util/SubgraphUtils' +import { + shouldIncludeSentTxs, + shouldIncludeReceivedTxs +} from '../util/SubgraphUtils' export type CompleteWithdrawalData = { withdrawals: L2ToL1EventResultPlus[] @@ -65,17 +68,18 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { const { address: walletAddress } = useAccount() - const showSentTxs = isAccountTypeLoading + // sent and received txs are always displayed for EOA but not for SCW + const includeSentTxs = isAccountTypeLoading ? false - : shouldShowSentTxs({ + : shouldIncludeSentTxs({ type: 'withdrawal', isSmartContractWallet, isConnectedToParentChain }) - const showReceivedTxs = isAccountTypeLoading + const includeReceivedTxs = isAccountTypeLoading ? false - : shouldShowReceivedTxs({ + : shouldIncludeReceivedTxs({ type: 'withdrawal', isSmartContractWallet, isConnectedToParentChain @@ -107,8 +111,8 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { _searchString ]) => fetchCompleteWithdrawalData({ - sender: showSentTxs ? _walletAddress : undefined, - receiver: showReceivedTxs ? _walletAddress : undefined, + sender: includeSentTxs ? _walletAddress : undefined, + receiver: includeReceivedTxs ? _walletAddress : undefined, l1Provider: _l1Provider, l2Provider: _l2Provider, pageNumber: _pageNumber, diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index 5d345779f1..3b93422ce2 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -119,7 +119,7 @@ export const tryFetchLatestSubgraphBlockNumber = async ( } } -export const shouldShowSentTxs = ({ +export const shouldIncludeSentTxs = ({ type, isSmartContractWallet, isConnectedToParentChain @@ -138,7 +138,7 @@ export const shouldShowSentTxs = ({ return true } -export const shouldShowReceivedTxs = ({ +export const shouldIncludeReceivedTxs = ({ type, isSmartContractWallet, isConnectedToParentChain From 47e3bc175782e39f4bfe667a0311690ef07070f4 Mon Sep 17 00:00:00 2001 From: Bartek Date: Thu, 5 Oct 2023 17:21:03 +0200 Subject: [PATCH 07/19] address comments --- .../TransactionHistory/TransactionHistory.tsx | 6 +- .../TransactionsTable/TransactionsTable.tsx | 2 - .../src/hooks/useDeposits.ts | 4 +- .../src/hooks/useWithdrawals.ts | 4 +- .../src/pages/api/withdrawals.ts | 64 +++++++++---------- .../fetchETHWithdrawalsFromEventLogs.ts | 2 +- 6 files changed, 38 insertions(+), 44 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx index 707525726e..efd12092b8 100644 --- a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionHistory.tsx @@ -1,6 +1,6 @@ import { Tab } from '@headlessui/react' import { Dispatch, SetStateAction, useMemo } from 'react' -import { useAccount, useNetwork } from 'wagmi' +import { useAccount } from 'wagmi' import { twMerge } from 'tailwind-merge' import { CompleteDepositData } from '../../hooks/useDeposits' @@ -17,7 +17,6 @@ import { FailedTransactionsWarning } from './FailedTransactionsWarning' import { isFailed, isPending } from '../../state/app/utils' import Image from 'next/image' import { TabButton } from '../common/Tab' -import { useAccountType } from '../../hooks/useAccountType' import { useCctpFetching, useCctpState } from '../../state/cctpState' import { MergedTransaction } from '../../state/app/state' import dayjs from 'dayjs' @@ -48,7 +47,6 @@ export const TransactionHistory = ({ setWithdrawalsPageParams: Dispatch> }) => { const { l1, l2 } = useNetworksAndSigners() - const { isSmartContractWallet } = useAccountType() const { pendingIds: pendingIdsCctp, transfers: transfersCctp, @@ -212,7 +210,6 @@ export const TransactionHistory = ({ pageParams={depositsPageParams} setPageParams={setDepositsPageParams} transactions={depositsData.transformedDeposits} - isSmartContractWallet={isSmartContractWallet} loading={depositsLoading} error={depositsError} /> @@ -229,7 +226,6 @@ export const TransactionHistory = ({ pageParams={withdrawalsPageParams} setPageParams={setWithdrawalsPageParams} transactions={withdrawalsData.transformedWithdrawals} - isSmartContractWallet={isSmartContractWallet} loading={withdrawalsLoading} error={withdrawalsError} /> diff --git a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx index 13da0f25b5..5d8bc52bff 100644 --- a/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransactionHistory/TransactionsTable/TransactionsTable.tsx @@ -164,7 +164,6 @@ export type TransactionsTableProps = { pageParams: PageParams setPageParams: Dispatch> transactions: MergedTransaction[] - isSmartContractWallet?: boolean loading: boolean error: boolean } @@ -174,7 +173,6 @@ export function TransactionsTable({ pageParams, setPageParams, transactions, - isSmartContractWallet, loading, error }: TransactionsTableProps) { diff --git a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts index 6b96c718bc..15d479fa4c 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useDeposits.ts @@ -59,7 +59,9 @@ export const useDeposits = (depositPageParams: PageParams) => { const { address: walletAddress } = useAccount() - // sent and received txs are always displayed for EOA but not for SCW + // SCW address is tied to a specific network + // that's why we need to limit shown txs either to sent or received funds + // otherwise we'd display funds for a different network, which could be someone else's account const includeSentTxs = isAccountTypeLoading ? false : shouldIncludeSentTxs({ diff --git a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts index 7c95648fe0..10a5e6852a 100644 --- a/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/hooks/useWithdrawals.ts @@ -68,7 +68,9 @@ export const useWithdrawals = (withdrawalPageParams: PageParams) => { const { address: walletAddress } = useAccount() - // sent and received txs are always displayed for EOA but not for SCW + // SCW address is tied to a specific network + // that's why we need to limit shown txs either to sent or received funds + // otherwise we'd display funds for a different network, which could be someone else's account const includeSentTxs = isAccountTypeLoading ? false : shouldIncludeSentTxs({ diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index 16136caf91..732848a9ee 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -74,41 +74,37 @@ export default async function handler( const subgraphResult = await getL2SubgraphClient(Number(l2ChainId)).query({ query: gql`{ - withdrawals( - where: { - or: [ - ${ - sender - ? `{ sender: "${sender}", ${additionalFilters} },` - : '' - } - ${ - receiver - ? `{ receiver: "${receiver}", ${additionalFilters} },` - : '' - } - ] + withdrawals( + where: { + or: [ + ${sender ? `{ sender: "${sender}", ${additionalFilters} },` : ''} + ${ + receiver + ? `{ receiver: "${receiver}", ${additionalFilters} },` + : '' } - orderBy: l2BlockTimestamp - orderDirection: desc - first: ${Number(pageSize)}, - skip: ${Number(page) * Number(pageSize)} - ) { - id, - type, - sender, - receiver, - ethValue, - l1Token { - id - }, - tokenAmount, - isClassic, - l2BlockTimestamp, - l2TxHash, - l2BlockNum - } - }` + ] + } + orderBy: l2BlockTimestamp + orderDirection: desc + first: ${Number(pageSize)}, + skip: ${Number(page) * Number(pageSize)} + ) { + id, + type, + sender, + receiver, + ethValue, + l1Token { + id + }, + tokenAmount, + isClassic, + l2BlockTimestamp, + l2TxHash, + l2BlockNum + } + }` }) const transactions: FetchWithdrawalsFromSubgraphResult[] = diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts index 696dc343b9..4632cfa199 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts @@ -10,7 +10,7 @@ import { L2ToL1MessageReader } from '@arbitrum/sdk' * @param query.toBlock Stop at this block number (including) * @param query.l2Provider Provider for the L2 network */ -export async function fetchETHWithdrawalsFromEventLogs({ +export function fetchETHWithdrawalsFromEventLogs({ sender, fromBlock, toBlock, From f825dfddf9daec85aaa4ccc967c61760cb049ebb Mon Sep 17 00:00:00 2001 From: Bartek Date: Thu, 5 Oct 2023 17:21:25 +0200 Subject: [PATCH 08/19] address comments --- packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index 8eeb06dadd..01c95ae9fc 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -42,7 +42,7 @@ export async function attachTimestampToTokenWithdrawals({ l2Provider: Provider }) { return Promise.all( - [...withdrawals].map(async withdrawal => { + withdrawals.map(async withdrawal => { const txReceipt = await l2Provider.getTransactionReceipt( withdrawal.txHash ) From 35fc3254e9632fe2c39650015cb4f031a9e896ae Mon Sep 17 00:00:00 2001 From: Bartek Date: Fri, 6 Oct 2023 12:31:01 +0200 Subject: [PATCH 09/19] review changes --- .../__tests__/fetchETHWithdrawalsTestHelpers.ts | 4 ++-- .../withdrawals/fetchETHWithdrawalsFromEventLogs.ts | 10 +++++----- .../src/util/withdrawals/fetchWithdrawals.ts | 10 +++++----- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts index 9295f467cb..0d6ea02aee 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchETHWithdrawalsTestHelpers.ts @@ -1,10 +1,10 @@ import { StaticJsonRpcProvider } from '@ethersproject/providers' -const sender = '0xd898275e8b9428429155752f89fe0899ce232830' +const receiver = '0xd898275e8b9428429155752f89fe0899ce232830' const l2Provider = new StaticJsonRpcProvider('https://arb1.arbitrum.io/rpc') const baseQuery = { - sender, + receiver, l2Provider } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts index 4632cfa199..ad8dff4bd0 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchETHWithdrawalsFromEventLogs.ts @@ -5,23 +5,23 @@ import { L2ToL1MessageReader } from '@arbitrum/sdk' * Fetches initiated ETH withdrawals from event logs in range of [fromBlock, toBlock]. * * @param query Query params - * @param query.toAddress Address that will receive the funds + * @param query.receiver Address that will receive the funds * @param query.fromBlock Start at this block number (including) * @param query.toBlock Stop at this block number (including) * @param query.l2Provider Provider for the L2 network */ export function fetchETHWithdrawalsFromEventLogs({ - sender, + receiver, fromBlock, toBlock, l2Provider }: { - sender?: string + receiver?: string fromBlock: BlockTag toBlock: BlockTag l2Provider: Provider }) { - if (typeof sender === 'undefined') { + if (typeof receiver === 'undefined') { return [] } // funds sent by this address @@ -29,6 +29,6 @@ export function fetchETHWithdrawalsFromEventLogs({ l2Provider, { fromBlock, toBlock }, undefined, - sender + receiver ) } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index ddd1caaaf1..615b7f7caa 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -1,3 +1,4 @@ +import { constants } from 'ethers' import { Provider } from '@ethersproject/providers' import { fetchETHWithdrawalsFromEventLogs } from './fetchETHWithdrawalsFromEventLogs' @@ -19,7 +20,6 @@ import { WithdrawalInitiated } from '../../hooks/arbTokenBridge.types' import { fetchL2Gateways } from '../fetchL2Gateways' -import { constants } from 'ethers' export type FetchWithdrawalsParams = { sender?: string @@ -86,7 +86,7 @@ export const fetchWithdrawals = async ({ searchString }), fetchETHWithdrawalsFromEventLogs({ - sender, + receiver, fromBlock: toBlock + 1, toBlock: 'latest', l2Provider: l2Provider @@ -113,7 +113,7 @@ export const fetchWithdrawals = async ({ }) // get ETH and token withdrawals that will be displayed on the current page - const partialWithdrawalsFromEventLogs = [ + const paginatedWithdrawalsFromEventLogs = [ ...ethWithdrawalsFromEventLogs, ...tokenWithdrawalsFromEventLogsWithTimestamp ] @@ -121,7 +121,7 @@ export const fetchWithdrawals = async ({ .slice(currentPageStart, currentPageEnd) const mappedTokenWithdrawalsFromEventLogs = await Promise.all( - partialWithdrawalsFromEventLogs + paginatedWithdrawalsFromEventLogs .filter(withdrawal => !isEthWithdrawal(withdrawal)) .map(withdrawal => mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( @@ -143,7 +143,7 @@ export const fetchWithdrawals = async ({ l2ChainID ) ), - ...partialWithdrawalsFromEventLogs + ...paginatedWithdrawalsFromEventLogs .filter(isEthWithdrawal) .map(withdrawal => mapETHWithdrawalToL2ToL1EventResult( From 17d26e331e0cae1bc690a74859335338516f37fe Mon Sep 17 00:00:00 2001 From: Bartek Date: Fri, 6 Oct 2023 15:44:37 +0200 Subject: [PATCH 10/19] tsdoc fix --- .../src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index 1742ad9b2f..cfe7559e8b 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -5,7 +5,8 @@ import { Erc20Bridger } from '@arbitrum/sdk' * Fetches initiated token withdrawals from event logs in range of [fromBlock, toBlock]. * * @param query Query params - * @param query.address Address that initiated the withdrawal, or received the funds + * @param query.sender Address that initiated the withdrawal + * @param query.receiver Address that received the funds * @param query.fromBlock Start at this block number (including) * @param query.toBlock Stop at this block number (including) * @param query.l2Provider Provider for the L2 network From 54ae273444914152d60581a5e9e41a417343d5c9 Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 13:45:23 +0200 Subject: [PATCH 11/19] review comments and clean up --- .../src/pages/api/deposits.ts | 23 +++++------ .../src/pages/api/withdrawals.ts | 23 +++++------ .../src/util/SubgraphUtils.ts | 40 ++++++++++++++++++- .../deposits/fetchDepositsFromSubgraph.ts | 3 +- ...fetchTokenWithdrawalsFromEventLogs.test.ts | 4 +- .../fetchTokenWithdrawalsFromEventLogs.ts | 24 ++++------- .../src/util/withdrawals/fetchWithdrawals.ts | 12 +++--- .../fetchWithdrawalsFromSubgraph.ts | 3 +- .../src/util/withdrawals/helpers.ts | 32 +++++++-------- 9 files changed, 91 insertions(+), 73 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts index c1dc4124d2..03f6222fca 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts @@ -1,7 +1,10 @@ import { NextApiRequest, NextApiResponse } from 'next' import { gql } from '@apollo/client' import { FetchDepositsFromSubgraphResult } from '../../util/deposits/fetchDepositsFromSubgraph' -import { getL1SubgraphClient } from '../../util/SubgraphUtils' +import { + getAdditionalSubgraphFilters, + getL1SubgraphClient +} from '../../util/SubgraphUtils' // Extending the standard NextJs request with Deposit-params type NextApiRequestWithDepositParams = NextApiRequest & { @@ -59,18 +62,12 @@ export default async function handler( }) } - const additionalFilters = `${ - typeof fromBlock !== 'undefined' - ? `blockCreatedAt_gte: ${Number(fromBlock)},` - : '' - } - ${ - typeof toBlock !== 'undefined' - ? `blockCreatedAt_lte: ${Number(toBlock)},` - : '' - } - ${search ? `transactionHash_contains: "${search}"` : ''} - ` + const additionalFilters = getAdditionalSubgraphFilters({ + type: 'deposit', + fromBlock, + toBlock, + search + }) const subgraphResult = await getL1SubgraphClient(Number(l2ChainId)).query({ query: gql(`{ diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index 732848a9ee..6e9c131305 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -1,7 +1,10 @@ import { NextApiRequest, NextApiResponse } from 'next' import { gql } from '@apollo/client' import { FetchWithdrawalsFromSubgraphResult } from '../../util/withdrawals/fetchWithdrawalsFromSubgraph' -import { getL2SubgraphClient } from '../../util/SubgraphUtils' +import { + getAdditionalSubgraphFilters, + getL2SubgraphClient +} from '../../util/SubgraphUtils' // Extending the standard NextJs request with Withdrawal-params type NextApiRequestWithWithdrawalParams = NextApiRequest & { @@ -59,18 +62,12 @@ export default async function handler( }) } - const additionalFilters = `${ - typeof fromBlock !== 'undefined' - ? `l2BlockNum_gte: ${Number(fromBlock)},` - : '' - } - ${ - typeof toBlock !== 'undefined' - ? `l2BlockNum_lte: ${Number(toBlock)},` - : '' - } - ${search ? `l2TxHash_contains: "${search}"` : ''} - ` + const additionalFilters = getAdditionalSubgraphFilters({ + type: 'withdrawal', + fromBlock, + toBlock, + search + }) const subgraphResult = await getL2SubgraphClient(Number(l2ChainId)).query({ query: gql`{ diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index 3b93422ce2..f8672d282c 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -1,5 +1,7 @@ import fetch from 'cross-fetch' import { ApolloClient, HttpLink, InMemoryCache, gql } from '@apollo/client' +import { WithdrawalInitiatedEvent } from '@arbitrum/sdk/dist/lib/abi/L2ArbitrumGateway' +import { EventArgs } from '@arbitrum/sdk/dist/lib/dataEntities/event' const L1SubgraphClient = { ArbitrumOne: new ApolloClient({ @@ -148,7 +150,7 @@ export const shouldIncludeReceivedTxs = ({ isConnectedToParentChain: boolean }) => { if (isSmartContractWallet) { - // show txs sent from this account for: + // show txs sent to this account for: // 1. withdrawals if we are connected to the parent chain, or // 2. deposits if we are connected to the child chain return isConnectedToParentChain ? type === 'withdrawal' : type === 'deposit' @@ -156,3 +158,39 @@ export const shouldIncludeReceivedTxs = ({ // always show for EOA return true } + +export const getAdditionalSubgraphFilters = ({ + type, + fromBlock, + toBlock, + search +}: { + type: 'deposit' | 'withdrawal' + fromBlock?: string + toBlock?: string + search?: string +}) => { + const blockParamKey = type === 'deposit' ? 'blockCreatedAt' : 'l2BlockNum' + + const fromBlockParam = + typeof fromBlock !== 'undefined' + ? `${blockParamKey}_gte: ${Number(fromBlock)},` + : '' + + const toBlockParam = + typeof toBlock !== 'undefined' + ? `${blockParamKey}_lte: ${Number(toBlock)}` + : '' + + const searchParam = search ? `l2TxHash_contains: "${search}"` : '' + + return fromBlockParam + toBlockParam + searchParam +} + +export const dedupeEvents = ( + events: (EventArgs & { + txHash: string + })[] +) => { + return [...new Map(events.map(item => [item.txHash, item])).values()] +} diff --git a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts index 182f7d166d..e2fa0164b8 100644 --- a/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/deposits/fetchDepositsFromSubgraph.ts @@ -25,7 +25,8 @@ export type FetchDepositsFromSubgraphResult = { * Fetches initiated deposits (ETH + Tokens) from subgraph in range of [fromBlock, toBlock] and pageParams. * * @param query Query params - * @param query.address Account address + * @param query.sender Address that initiated the withdrawal + * @param query.receiver Address that received the funds * @param query.fromBlock Start at this block number (including) * @param query.toBlock Stop at this block number (including) * @param query.l2ChainId Chain id for the L2 network diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts index 8da04b5b3e..fdc130d46c 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts @@ -10,9 +10,7 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { // TODO: This is a temporary fix, when Event Logs are enabled for custom address // we will be able to use the same properties, and remove the need to assign sender to address const query = getQueryCoveringClassicOnlyWithoutResults() - const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query - }) + const result = await fetchTokenWithdrawalsFromEventLogs(query) expect(result).toHaveLength(0) }) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index cfe7559e8b..8f5527845b 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -1,5 +1,6 @@ import { Provider, BlockTag } from '@ethersproject/providers' import { Erc20Bridger } from '@arbitrum/sdk' +import { dedupeEvents } from '../SubgraphUtils' /** * Fetches initiated token withdrawals from event logs in range of [fromBlock, toBlock]. @@ -28,13 +29,12 @@ export async function fetchTokenWithdrawalsFromEventLogs({ l2GatewayAddresses?: string[] }) { const erc20Bridger = await Erc20Bridger.fromProvider(l2Provider) + const promises: ReturnType[] = [] - const promises = l2GatewayAddresses.flatMap(gatewayAddress => { - const events = [] - + l2GatewayAddresses.forEach(gatewayAddress => { // funds sent by this address if (sender) { - events.push( + promises.push( erc20Bridger.getL2WithdrawalEvents( l2Provider, gatewayAddress, @@ -48,7 +48,7 @@ export async function fetchTokenWithdrawalsFromEventLogs({ // funds received by this address if (receiver) { - events.push( + promises.push( erc20Bridger.getL2WithdrawalEvents( l2Provider, gatewayAddress, @@ -59,18 +59,8 @@ export async function fetchTokenWithdrawalsFromEventLogs({ ) ) } - - return events }) - return ( - (await Promise.all(promises)) - .flat() - // when getting funds received by this address we will also get duplicate txs returned in 'funds sent by this address' - // we have to filter them out - .filter( - (item, index, self) => - index === self.findIndex(tx => tx.txHash === item.txHash) - ) - ) + // when getting funds received by this address we will also get duplicate txs returned in 'funds sent by this address' + return dedupeEvents((await Promise.all(promises)).flat()) } diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index 615b7f7caa..19dad7f81e 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -5,7 +5,7 @@ import { fetchETHWithdrawalsFromEventLogs } from './fetchETHWithdrawalsFromEvent import { EthWithdrawal, - attachTimestampToTokenWithdrawals, + attachTimestampToTokenWithdrawal, isEthWithdrawal, mapETHWithdrawalToL2ToL1EventResult, mapTokenWithdrawalFromEventLogsToL2ToL1EventResult, @@ -106,11 +106,11 @@ export const fetchWithdrawals = async ({ const currentPageEnd = currentPageStart + pageSize // we need timestamps to sort token withdrawals along ETH withdrawals - const tokenWithdrawalsFromEventLogsWithTimestamp = - await attachTimestampToTokenWithdrawals({ - withdrawals: tokenWithdrawalsFromEventLogs, - l2Provider - }) + const tokenWithdrawalsFromEventLogsWithTimestamp = await Promise.all( + tokenWithdrawalsFromEventLogs.map(withdrawal => + attachTimestampToTokenWithdrawal({ withdrawal, l2Provider }) + ) + ) // get ETH and token withdrawals that will be displayed on the current page const paginatedWithdrawalsFromEventLogs = [ diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts index 13b4972419..98e8d7ce59 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawalsFromSubgraph.ts @@ -20,7 +20,8 @@ export type FetchWithdrawalsFromSubgraphResult = { * Fetches initiated withdrawals (ETH + Token) from subgraph in range of [fromBlock, toBlock] and pageParams. * * @param query Query params - * @param query.address Account address + * @param query.sender Address that initiated the withdrawal + * @param query.receiver Address that received the funds * @param query.fromBlock Start at this block number (including) * @param query.toBlock Stop at this block number (including) * @param query.l2ChainId ChainId for the L2 network diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index 01c95ae9fc..e2adaaa3e4 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -34,32 +34,28 @@ export const updateAdditionalWithdrawalData = async ( return l2toL1TxWithDeadline } -export async function attachTimestampToTokenWithdrawals({ - withdrawals, +export async function attachTimestampToTokenWithdrawal({ + withdrawal, l2Provider }: { - withdrawals: WithdrawalInitiated[] + withdrawal: WithdrawalInitiated l2Provider: Provider }) { - return Promise.all( - withdrawals.map(async withdrawal => { - const txReceipt = await l2Provider.getTransactionReceipt( - withdrawal.txHash - ) - const l2TxReceipt = new L2TransactionReceipt(txReceipt) - const [event] = l2TxReceipt.getL2ToL1Events() + const txReceipt = await l2Provider.getTransactionReceipt(withdrawal.txHash) + const l2TxReceipt = new L2TransactionReceipt(txReceipt) + const [event] = l2TxReceipt.getL2ToL1Events() - return { - ...withdrawal, - timestamp: event?.timestamp - } - }) - ) + return { + ...withdrawal, + timestamp: event?.timestamp + } } +/** + * `l2TxHash` exists on result from subgraph + * `transactionHash` exists on result from event logs + */ export async function mapETHWithdrawalToL2ToL1EventResult( - // `l2TxHash` exists on result from subgraph - // `transactionHash` exists on result from event logs event: EthWithdrawal, l1Provider: Provider, l2Provider: Provider, From 1638fc503425f356916a906f17a8c1524644a9fa Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 13:54:35 +0200 Subject: [PATCH 12/19] revert filters --- .../src/pages/api/deposits.ts | 23 ++++++++------- .../src/pages/api/withdrawals.ts | 23 ++++++++------- .../src/util/SubgraphUtils.ts | 28 ------------------- 3 files changed, 26 insertions(+), 48 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts index 03f6222fca..c1dc4124d2 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/deposits.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/deposits.ts @@ -1,10 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next' import { gql } from '@apollo/client' import { FetchDepositsFromSubgraphResult } from '../../util/deposits/fetchDepositsFromSubgraph' -import { - getAdditionalSubgraphFilters, - getL1SubgraphClient -} from '../../util/SubgraphUtils' +import { getL1SubgraphClient } from '../../util/SubgraphUtils' // Extending the standard NextJs request with Deposit-params type NextApiRequestWithDepositParams = NextApiRequest & { @@ -62,12 +59,18 @@ export default async function handler( }) } - const additionalFilters = getAdditionalSubgraphFilters({ - type: 'deposit', - fromBlock, - toBlock, - search - }) + const additionalFilters = `${ + typeof fromBlock !== 'undefined' + ? `blockCreatedAt_gte: ${Number(fromBlock)},` + : '' + } + ${ + typeof toBlock !== 'undefined' + ? `blockCreatedAt_lte: ${Number(toBlock)},` + : '' + } + ${search ? `transactionHash_contains: "${search}"` : ''} + ` const subgraphResult = await getL1SubgraphClient(Number(l2ChainId)).query({ query: gql(`{ diff --git a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts index 6e9c131305..732848a9ee 100644 --- a/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts +++ b/packages/arb-token-bridge-ui/src/pages/api/withdrawals.ts @@ -1,10 +1,7 @@ import { NextApiRequest, NextApiResponse } from 'next' import { gql } from '@apollo/client' import { FetchWithdrawalsFromSubgraphResult } from '../../util/withdrawals/fetchWithdrawalsFromSubgraph' -import { - getAdditionalSubgraphFilters, - getL2SubgraphClient -} from '../../util/SubgraphUtils' +import { getL2SubgraphClient } from '../../util/SubgraphUtils' // Extending the standard NextJs request with Withdrawal-params type NextApiRequestWithWithdrawalParams = NextApiRequest & { @@ -62,12 +59,18 @@ export default async function handler( }) } - const additionalFilters = getAdditionalSubgraphFilters({ - type: 'withdrawal', - fromBlock, - toBlock, - search - }) + const additionalFilters = `${ + typeof fromBlock !== 'undefined' + ? `l2BlockNum_gte: ${Number(fromBlock)},` + : '' + } + ${ + typeof toBlock !== 'undefined' + ? `l2BlockNum_lte: ${Number(toBlock)},` + : '' + } + ${search ? `l2TxHash_contains: "${search}"` : ''} + ` const subgraphResult = await getL2SubgraphClient(Number(l2ChainId)).query({ query: gql`{ diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index f8672d282c..e323afd964 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -159,34 +159,6 @@ export const shouldIncludeReceivedTxs = ({ return true } -export const getAdditionalSubgraphFilters = ({ - type, - fromBlock, - toBlock, - search -}: { - type: 'deposit' | 'withdrawal' - fromBlock?: string - toBlock?: string - search?: string -}) => { - const blockParamKey = type === 'deposit' ? 'blockCreatedAt' : 'l2BlockNum' - - const fromBlockParam = - typeof fromBlock !== 'undefined' - ? `${blockParamKey}_gte: ${Number(fromBlock)},` - : '' - - const toBlockParam = - typeof toBlock !== 'undefined' - ? `${blockParamKey}_lte: ${Number(toBlock)}` - : '' - - const searchParam = search ? `l2TxHash_contains: "${search}"` : '' - - return fromBlockParam + toBlockParam + searchParam -} - export const dedupeEvents = ( events: (EventArgs & { txHash: string From bad16958ca067607fa84b07724116c9c0cff5988 Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 13:58:19 +0200 Subject: [PATCH 13/19] clean up --- .../__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts | 8 ++------ .../arb-token-bridge-ui/src/util/withdrawals/helpers.ts | 4 ++++ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts index fdc130d46c..ddde9186c3 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/__tests__/fetchTokenWithdrawalsFromEventLogs.test.ts @@ -17,9 +17,7 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { it('fetches some token withdrawals from event logs pre-nitro', async () => { const query = getQueryCoveringClassicOnlyWithResults() - const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query - }) + const result = await fetchTokenWithdrawalsFromEventLogs(query) expect(result).toHaveLength(1) expect(result).toEqual( @@ -34,9 +32,7 @@ describe('fetchTokenWithdrawalsFromEventLogs', () => { it('fetches some token withdrawals from event logs pre-nitro and post-nitro', async () => { const query = getQueryCoveringClassicAndNitroWithResults() - const result = await fetchTokenWithdrawalsFromEventLogs({ - ...query - }) + const result = await fetchTokenWithdrawalsFromEventLogs(query) expect(result).toHaveLength(2) expect(result).toEqual( diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index e2adaaa3e4..550031ea2f 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -15,6 +15,10 @@ import { } from '../../hooks/arbTokenBridge.types' import { getExecutedMessagesCacheKey } from '../../hooks/useArbTokenBridge' +/** + * `l2TxHash` exists on result from subgraph + * `transactionHash` exists on result from event logs + */ export type EthWithdrawal = L2ToL1EventResult & { l2TxHash?: string transactionHash?: string From 40c13eeead5665e8883393bc02de5a338466f6e3 Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 14:13:35 +0200 Subject: [PATCH 14/19] move dedupe events --- .../arb-token-bridge-ui/src/util/SubgraphUtils.ts | 10 ---------- .../withdrawals/fetchTokenWithdrawalsFromEventLogs.ts | 11 ++++++++++- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts index e323afd964..e139566318 100644 --- a/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts +++ b/packages/arb-token-bridge-ui/src/util/SubgraphUtils.ts @@ -1,7 +1,5 @@ import fetch from 'cross-fetch' import { ApolloClient, HttpLink, InMemoryCache, gql } from '@apollo/client' -import { WithdrawalInitiatedEvent } from '@arbitrum/sdk/dist/lib/abi/L2ArbitrumGateway' -import { EventArgs } from '@arbitrum/sdk/dist/lib/dataEntities/event' const L1SubgraphClient = { ArbitrumOne: new ApolloClient({ @@ -158,11 +156,3 @@ export const shouldIncludeReceivedTxs = ({ // always show for EOA return true } - -export const dedupeEvents = ( - events: (EventArgs & { - txHash: string - })[] -) => { - return [...new Map(events.map(item => [item.txHash, item])).values()] -} diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts index 8f5527845b..0831ed38e2 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchTokenWithdrawalsFromEventLogs.ts @@ -1,6 +1,15 @@ import { Provider, BlockTag } from '@ethersproject/providers' import { Erc20Bridger } from '@arbitrum/sdk' -import { dedupeEvents } from '../SubgraphUtils' +import { EventArgs } from '@arbitrum/sdk/dist/lib/dataEntities/event' +import { WithdrawalInitiatedEvent } from '@arbitrum/sdk/dist/lib/abi/L2ArbitrumGateway' + +function dedupeEvents( + events: (EventArgs & { + txHash: string + })[] +) { + return [...new Map(events.map(item => [item.txHash, item])).values()] +} /** * Fetches initiated token withdrawals from event logs in range of [fromBlock, toBlock]. From 86a25d43299baf21f021f5f6e65e6b2cd46b0061 Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 14:28:04 +0200 Subject: [PATCH 15/19] sorting --- .../src/util/withdrawals/fetchWithdrawals.ts | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index 19dad7f81e..a218dc5b05 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -1,4 +1,4 @@ -import { constants } from 'ethers' +import { BigNumber, constants } from 'ethers' import { Provider } from '@ethersproject/providers' import { fetchETHWithdrawalsFromEventLogs } from './fetchETHWithdrawalsFromEventLogs' @@ -33,6 +33,17 @@ export type FetchWithdrawalsParams = { searchString?: string } +type Timestamped = { + timestamp?: BigNumber +} + +function sortByTimestampDescending(a: Timestamped, b: Timestamped) { + const aTimestamp = a.timestamp ?? constants.Zero + const bTimestamp = b.timestamp ?? constants.Zero + + return aTimestamp.gt(bTimestamp) ? -1 : 1 +} + /* Fetch complete withdrawals - both ETH and Token withdrawals from subgraph and event logs into one list */ /* Also fills in any additional data required per transaction for our UI logic to work well */ export const fetchWithdrawals = async ({ @@ -117,7 +128,7 @@ export const fetchWithdrawals = async ({ ...ethWithdrawalsFromEventLogs, ...tokenWithdrawalsFromEventLogsWithTimestamp ] - .sort((a, b) => (a.timestamp?.gt(b.timestamp || constants.Zero) ? -1 : 1)) + .sort(sortByTimestampDescending) .slice(currentPageStart, currentPageEnd) const mappedTokenWithdrawalsFromEventLogs = await Promise.all( @@ -157,7 +168,7 @@ export const fetchWithdrawals = async ({ ...mappedTokenWithdrawalsFromEventLogs ] .filter((msg): msg is L2ToL1EventResultPlus => typeof msg !== 'undefined') - .sort((msgA, msgB) => +msgA.timestamp - +msgB.timestamp) + .sort(sortByTimestampDescending) const finalL2ToL1Txns: L2ToL1EventResultPlus[] = await Promise.all( l2ToL1Txns.map(withdrawal => From 241706d28b341bcba23ff748ac166f63a947247e Mon Sep 17 00:00:00 2001 From: Bartek Date: Tue, 10 Oct 2023 15:32:42 +0200 Subject: [PATCH 16/19] is token withdrawal method --- .../src/util/withdrawals/fetchWithdrawals.ts | 6 +++--- .../arb-token-bridge-ui/src/util/withdrawals/helpers.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index a218dc5b05..f9d8fbb039 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -6,7 +6,7 @@ import { fetchETHWithdrawalsFromEventLogs } from './fetchETHWithdrawalsFromEvent import { EthWithdrawal, attachTimestampToTokenWithdrawal, - isEthWithdrawal, + isTokenWithdrawal, mapETHWithdrawalToL2ToL1EventResult, mapTokenWithdrawalFromEventLogsToL2ToL1EventResult, mapWithdrawalToL2ToL1EventResult, @@ -133,7 +133,7 @@ export const fetchWithdrawals = async ({ const mappedTokenWithdrawalsFromEventLogs = await Promise.all( paginatedWithdrawalsFromEventLogs - .filter(withdrawal => !isEthWithdrawal(withdrawal)) + .filter(isTokenWithdrawal) .map(withdrawal => mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( withdrawal as WithdrawalInitiated, @@ -155,7 +155,7 @@ export const fetchWithdrawals = async ({ ) ), ...paginatedWithdrawalsFromEventLogs - .filter(isEthWithdrawal) + .filter(withdrawal => !isTokenWithdrawal(withdrawal)) .map(withdrawal => mapETHWithdrawalToL2ToL1EventResult( withdrawal as EthWithdrawal, diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index 550031ea2f..6dd693475f 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -162,10 +162,10 @@ export async function attachNodeBlockDeadlineToEvent( } } -export function isEthWithdrawal( +export function isTokenWithdrawal( withdrawal: WithdrawalInitiated | EthWithdrawal -): withdrawal is EthWithdrawal { - return typeof (withdrawal as EthWithdrawal).ethBlockNum !== 'undefined' +): withdrawal is WithdrawalInitiated { + return typeof (withdrawal as WithdrawalInitiated).l1Token !== 'undefined' } export async function mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( From c637e43da1564857845f5e86b9b8098360ceaadc Mon Sep 17 00:00:00 2001 From: Bartek Date: Wed, 11 Oct 2023 13:02:10 +0200 Subject: [PATCH 17/19] better types --- .../src/util/withdrawals/fetchWithdrawals.ts | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index f9d8fbb039..c5e2332f87 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -131,17 +131,26 @@ export const fetchWithdrawals = async ({ .sort(sortByTimestampDescending) .slice(currentPageStart, currentPageEnd) + const paginatedTokenWithdrawalsFromEventLogs: WithdrawalInitiated[] = [] + const paginatedEthWithdrawalsFromEventLogs: EthWithdrawal[] = [] + + for (const withdrawal of paginatedWithdrawalsFromEventLogs) { + if (isTokenWithdrawal(withdrawal)) { + paginatedTokenWithdrawalsFromEventLogs.push(withdrawal) + } else { + paginatedEthWithdrawalsFromEventLogs.push(withdrawal) + } + } + const mappedTokenWithdrawalsFromEventLogs = await Promise.all( - paginatedWithdrawalsFromEventLogs - .filter(isTokenWithdrawal) - .map(withdrawal => - mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( - withdrawal as WithdrawalInitiated, - l1Provider, - l2Provider, - l2ChainID - ) + paginatedTokenWithdrawalsFromEventLogs.map(withdrawal => + mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( + withdrawal, + l1Provider, + l2Provider, + l2ChainID ) + ) ) const l2ToL1Txns = [ @@ -154,16 +163,14 @@ export const fetchWithdrawals = async ({ l2ChainID ) ), - ...paginatedWithdrawalsFromEventLogs - .filter(withdrawal => !isTokenWithdrawal(withdrawal)) - .map(withdrawal => - mapETHWithdrawalToL2ToL1EventResult( - withdrawal as EthWithdrawal, - l1Provider, - l2Provider, - l2ChainID - ) + ...paginatedEthWithdrawalsFromEventLogs.map(withdrawal => + mapETHWithdrawalToL2ToL1EventResult( + withdrawal as EthWithdrawal, + l1Provider, + l2Provider, + l2ChainID ) + ) ])), ...mappedTokenWithdrawalsFromEventLogs ] From d97d2a3e80e7d45706e08b386407aed71c23befa Mon Sep 17 00:00:00 2001 From: Bartek Date: Wed, 11 Oct 2023 13:03:53 +0200 Subject: [PATCH 18/19] remove type casting --- .../src/util/withdrawals/fetchWithdrawals.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts index c5e2332f87..bf2f631eaf 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/fetchWithdrawals.ts @@ -165,7 +165,7 @@ export const fetchWithdrawals = async ({ ), ...paginatedEthWithdrawalsFromEventLogs.map(withdrawal => mapETHWithdrawalToL2ToL1EventResult( - withdrawal as EthWithdrawal, + withdrawal, l1Provider, l2Provider, l2ChainID From 6dfcedbe113fc17aa3f45a88768d22eb72f1b8b9 Mon Sep 17 00:00:00 2001 From: Bartek Date: Wed, 11 Oct 2023 13:05:21 +0200 Subject: [PATCH 19/19] comments clean up --- .../arb-token-bridge-ui/src/util/withdrawals/helpers.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts index 6dd693475f..30718852fb 100644 --- a/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts +++ b/packages/arb-token-bridge-ui/src/util/withdrawals/helpers.ts @@ -55,10 +55,6 @@ export async function attachTimestampToTokenWithdrawal({ } } -/** - * `l2TxHash` exists on result from subgraph - * `transactionHash` exists on result from event logs - */ export async function mapETHWithdrawalToL2ToL1EventResult( event: EthWithdrawal, l1Provider: Provider, @@ -245,8 +241,6 @@ export async function mapTokenWithdrawalFromEventLogsToL2ToL1EventResult( } export async function mapWithdrawalToL2ToL1EventResult( - // `l2TxHash` exists on result from subgraph - // `transactionHash` exists on result from event logs withdrawal: FetchWithdrawalsFromSubgraphResult, l1Provider: Provider, l2Provider: Provider,