From 7981c2f90a19c86c270db282214a9b7dff9e5c85 Mon Sep 17 00:00:00 2001 From: Mati Dastugue Date: Wed, 22 Jun 2022 15:34:47 -0300 Subject: [PATCH] [Batch Viewer] Avoid multiple requests to Tenderly API (#128) * Remove unused useRef * Add undefined type to orders * usePreviousValue to detect any changes * Remove usePrevious function in volumeChart and replace with usePrevious hook * Add comment to clarify why the workaround is needed --- .../VolumeChart/VolumeChart.tsx | 19 +---- src/hooks/usePrevious.ts | 11 +++ src/hooks/useTxBatchTrades.tsx | 71 +++++++++---------- 3 files changed, 48 insertions(+), 53 deletions(-) create mode 100644 src/hooks/usePrevious.ts diff --git a/src/apps/explorer/components/SummaryCardsWidget/VolumeChart/VolumeChart.tsx b/src/apps/explorer/components/SummaryCardsWidget/VolumeChart/VolumeChart.tsx index e523b6bf9..e4fee19d4 100644 --- a/src/apps/explorer/components/SummaryCardsWidget/VolumeChart/VolumeChart.tsx +++ b/src/apps/explorer/components/SummaryCardsWidget/VolumeChart/VolumeChart.tsx @@ -29,6 +29,7 @@ import { } from 'apps/explorer/components/SummaryCardsWidget/VolumeChart/VolumeChartWidget' import { numberFormatter } from 'apps/explorer/components/SummaryCardsWidget/utils' import { useNetworkId } from 'state/network' +import { usePrevious } from 'hooks/usePrevious' const DEFAULT_CHART_HEIGHT = 214 // px @@ -64,20 +65,6 @@ function _formatAmount(amount: string): string { return formatSmart({ amount, precision: 0, decimals: 0 }) } -/* Store an ID to check if there is new data that - * requires the graph to be rendered. - * example: - - * */ -function usePreviousLastValueData(value: T): T | undefined { - const ref = useRef() - - useEffect(() => { - ref.current = value - }, [value]) - - return ref.current -} - function _buildChart( chartContainer: HTMLDivElement, width: number | undefined, @@ -209,8 +196,8 @@ export function VolumeChart({ const captionNameColor = getColorBySign(diffPercentageVolume || 0) const [crossHairData, setCrossHairData] = useState(null) const network = useNetworkId() - const previousPeriod = usePreviousLastValueData(period) - const previousNetwork = usePreviousLastValueData(network) + const previousPeriod = usePrevious(period) + const previousNetwork = usePrevious(network) const periodTitle = period && volumePeriodTitle.get(period) // reset the chart when the volume/network period is changed diff --git a/src/hooks/usePrevious.ts b/src/hooks/usePrevious.ts new file mode 100644 index 000000000..e646754ca --- /dev/null +++ b/src/hooks/usePrevious.ts @@ -0,0 +1,11 @@ +import { useEffect, useRef } from 'react' + +export function usePrevious(value: T): T | undefined { + const ref = useRef() + + useEffect(() => { + ref.current = value + }, [value]) + + return ref.current +} diff --git a/src/hooks/useTxBatchTrades.tsx b/src/hooks/useTxBatchTrades.tsx index 6ae8586d4..a849d008d 100644 --- a/src/hooks/useTxBatchTrades.tsx +++ b/src/hooks/useTxBatchTrades.tsx @@ -5,6 +5,7 @@ import { getTradesAccount, getTradesAndTransfers, Trade, Transfer, Account } fro import { useMultipleErc20 } from './useErc20' import { SingleErc20State } from 'state/erc20' import { Order } from 'api/operator' +import { usePrevious } from './usePrevious' interface TxBatchTrades { trades: Trade[] @@ -37,53 +38,49 @@ export function useTxBatchTrades( const [error, setError] = useState('') const [txBatchTrades, setTxBatchTrades] = useState({ trades: [], transfers: [] }) const [accounts, setAccounts] = useState() + const txOrders = usePrevious(JSON.stringify(orders?.map((o) => ({ owner: o.owner, kind: o.kind })))) // We need to do a deep comparison here to avoid useEffect to be called twice (Orders array is populated partially from different places) const [erc20Addresses, setErc20Addresses] = useState([]) const { value: valueErc20s, isLoading: areErc20Loading } = useMultipleErc20({ networkId, addresses: erc20Addresses }) - const ordersFoundInTx = orders?.length - const _fetchTxTrades = useCallback( - async (network: Network, _txHash: string): Promise => { - setIsLoading(true) - setError('') + const _fetchTxTrades = useCallback(async (network: Network, _txHash: string, orders: Order[]): Promise => { + setIsLoading(true) + setError('') - try { - const { transfers, trades } = await getTradesAndTransfers(network, _txHash) - const _accounts = Object.fromEntries(await getTradesAccount(network, _txHash, trades, transfers)) - const orderIds = orders?.map((order) => order.owner) || [] - const transfersWithKind: Transfer[] = transfers.reduce( - (acc, transfer) => - !orderIds.includes(transfer.from) && !orderIds.includes(transfer.to) ? [...acc, transfer] : acc, - [], - ) - - orders?.forEach((order) => { - const { owner, kind } = order - transfersWithKind.push( - ...transfers.filter((t) => [t.from, t.to].includes(owner)).map((transfer) => ({ ...transfer, kind })), - ) - }) + try { + const { transfers, trades } = await getTradesAndTransfers(network, _txHash) + const _accounts = Object.fromEntries(await getTradesAccount(network, _txHash, trades, transfers)) + const orderIds = orders.map((order) => order.owner) || [] + const transfersWithKind: Transfer[] = transfers.reduce( + (acc, transfer) => + !orderIds.includes(transfer.from) && !orderIds.includes(transfer.to) ? [...acc, transfer] : acc, + [], + ) - setErc20Addresses(transfers.map((transfer: Transfer): string => transfer.token)) - setTxBatchTrades({ trades, transfers: transfersWithKind }) - setAccounts(_accounts) - } catch (e) { - const msg = `Failed to fetch tx batch trades` - console.error(msg, e) - setError(msg) - } finally { - setIsLoading(false) - } - }, - [orders], - ) + orders.forEach((order) => { + const { owner, kind } = order + transfersWithKind.push( + ...transfers.filter((t) => [t.from, t.to].includes(owner)).map((transfer) => ({ ...transfer, kind })), + ) + }) + setErc20Addresses(transfers.map((transfer: Transfer): string => transfer.token)) + setTxBatchTrades({ trades, transfers }) + setAccounts(_accounts) + } catch (e) { + const msg = `Failed to fetch tx batch trades` + console.error(msg, e) + setError(msg) + } finally { + setIsLoading(false) + } + }, []) useEffect(() => { - if (!networkId || !ordersFoundInTx) { + if (!networkId || !txOrders) { return } - _fetchTxTrades(networkId, txHash) - }, [_fetchTxTrades, networkId, ordersFoundInTx, txHash]) + _fetchTxTrades(networkId, txHash, JSON.parse(txOrders)) + }, [_fetchTxTrades, networkId, txHash, txOrders]) return { txSettlement: { ...txBatchTrades, tokens: valueErc20s, accounts },