Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

Commit

Permalink
fix: transaction state 'resets' (#1092)
Browse files Browse the repository at this point in the history
* stop & start polling for token prices

* fix undefined error

* start polling again on modal close

* rename

* add comment

* stop/start polling to prevent add-liquidity txn state reset

* stop/start polling to prevent remove-liquidity txn state reset

* keep pollInterval local
  • Loading branch information
groninge01 authored Sep 19, 2024
1 parent 9bb8342 commit a0282ba
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 17 deletions.
11 changes: 10 additions & 1 deletion lib/modules/pool/actions/add-liquidity/form/AddLiquidityForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { useUserAccount } from '@/lib/modules/web3/UserAccountProvider'
import { ConnectWallet } from '@/lib/modules/web3/ConnectWallet'
import { BalAlert } from '@/lib/shared/components/alerts/BalAlert'
import { SafeAppAlert } from '@/lib/shared/components/alerts/SafeAppAlert'
import { useTokens } from '@/lib/modules/tokens/TokensProvider'

// small wrapper to prevent out of context error
export function AddLiquidityForm() {
Expand Down Expand Up @@ -87,6 +88,7 @@ function AddLiquidityMainForm() {
const { setValidationError } = useTokenInputsValidation()
const { balanceFor, isBalancesLoading } = useTokenBalances()
const { isConnected } = useUserAccount()
const { startTokenPricePolling } = useTokens()

useEffect(() => {
setPriceImpact(priceImpactQuery.data)
Expand Down Expand Up @@ -148,6 +150,13 @@ function AddLiquidityMainForm() {
}
}, [addLiquidityTxHash])

function onModalClose() {
// restart polling for token prices when modal is closed again
startTokenPricePolling()

previewModalDisclosure.onClose()
}

return (
<Box w="full" maxW="lg" mx="auto" pb="2xl">
<Card>
Expand Down Expand Up @@ -259,7 +268,7 @@ function AddLiquidityMainForm() {
finalFocusRef={nextBtn}
isOpen={previewModalDisclosure.isOpen}
onOpen={previewModalDisclosure.onOpen}
onClose={previewModalDisclosure.onClose}
onClose={onModalClose}
/>
{!!validTokens.length && (
<NativeAssetSelectModal
Expand Down
11 changes: 11 additions & 0 deletions lib/modules/pool/actions/add-liquidity/modal/AddLiquidityModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useOnUserAccountChanged } from '@/lib/modules/web3/useOnUserAccountChan
import { AddLiquiditySummary } from './AddLiquiditySummary'
import { useAddLiquidityReceipt } from '@/lib/modules/transactions/transaction-steps/receipts/receipt.hooks'
import { useUserAccount } from '@/lib/modules/web3/UserAccountProvider'
import { useTokens } from '@/lib/modules/tokens/TokensProvider'

type Props = {
isOpen: boolean
Expand All @@ -39,6 +40,8 @@ export function AddLiquidityModal({
const { pool, chain } = usePool()
const { redirectToPoolPage } = usePoolRedirect(pool)
const { userAddress } = useUserAccount()
const { stopTokenPricePolling } = useTokens()

const receiptProps = useAddLiquidityReceipt({
chain,
txHash: addLiquidityTxHash,
Expand All @@ -47,6 +50,14 @@ export function AddLiquidityModal({

useResetStepIndexOnOpen(isOpen, transactionSteps)

useEffect(() => {
if (isOpen) {
// stop polling for token prices when modal is opened to prevent unwanted re-renders
stopTokenPricePolling()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isOpen])

useEffect(() => {
if (addLiquidityTxHash && !window.location.pathname.includes(addLiquidityTxHash)) {
window.history.replaceState({}, '', `./add-liquidity/${addLiquidityTxHash}`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { parseUnits } from 'viem'
import { SimulationError } from '@/lib/shared/components/errors/SimulationError'
import { InfoIcon } from '@/lib/shared/components/icons/InfoIcon'
import { SafeAppAlert } from '@/lib/shared/components/alerts/SafeAppAlert'

import { useTokens } from '@/lib/modules/tokens/TokensProvider'
const TABS: ButtonGroupOption[] = [
{
value: 'proportional',
Expand Down Expand Up @@ -70,6 +70,7 @@ export function RemoveLiquidityForm() {
const { redirectToPoolPage } = usePoolRedirect(pool)
const nextBtn = useRef(null)
const [activeTab, setActiveTab] = useState(TABS[0])
const { startTokenPricePolling } = useTokens()

useEffect(() => {
setPriceImpact(priceImpactQuery.data)
Expand All @@ -91,6 +92,9 @@ export function RemoveLiquidityForm() {
}

const onModalClose = () => {
// restart polling for token prices when modal is closed again
startTokenPricePolling()

if (transactionSteps.lastTransactionConfirmingOrConfirmed) {
// If the transaction is confirming or confirmed, it's very likely that
// they no longer have a pool balance. To be safe, always redirect to the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useOnUserAccountChanged } from '@/lib/modules/web3/useOnUserAccountChan
import { RemoveLiquiditySummary } from './RemoveLiquiditySummary'
import { useRemoveLiquidityReceipt } from '@/lib/modules/transactions/transaction-steps/receipts/receipt.hooks'
import { useUserAccount } from '@/lib/modules/web3/UserAccountProvider'
import { useTokens } from '@/lib/modules/tokens/TokensProvider'

type Props = {
isOpen: boolean
Expand All @@ -38,6 +39,7 @@ export function RemoveLiquidityModal({
const { pool, chain } = usePool()
const { redirectToPoolPage } = usePoolRedirect(pool)
const { userAddress } = useUserAccount()
const { stopTokenPricePolling } = useTokens()

const receiptProps = useRemoveLiquidityReceipt({
chain,
Expand All @@ -47,6 +49,14 @@ export function RemoveLiquidityModal({

useResetStepIndexOnOpen(isOpen, transactionSteps)

useEffect(() => {
if (isOpen) {
// stop polling for token prices when modal is opened to prevent unwanted re-renders
stopTokenPricePolling()
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isOpen])

useEffect(() => {
if (removeLiquidityTxHash && !window.location.pathname.includes(removeLiquidityTxHash)) {
window.history.replaceState({}, '', `./remove-liquidity/${removeLiquidityTxHash}`)
Expand Down
2 changes: 1 addition & 1 deletion lib/modules/swap/SwapDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function OrderRoute() {

const queryData = simulationQuery.data as SdkSimulateSwapResponse
const orderRouteVersion = queryData ? queryData.protocolVersion : 2
const hopCount = queryData?.routes[0]?.hops?.length ?? 0
const hopCount = queryData ? queryData.routes[0]?.hops?.length : 0

return (
<HStack justify="space-between" w="full">
Expand Down
6 changes: 6 additions & 0 deletions lib/modules/swap/SwapForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import { parseSwapError } from './swap.helpers'
import { useUserAccount } from '../web3/UserAccountProvider'
import { ConnectWallet } from '../web3/ConnectWallet'
import { SafeAppAlert } from '@/lib/shared/components/alerts/SafeAppAlert'
import { useTokens } from '../tokens/TokensProvider'

export function SwapForm() {
const {
Expand Down Expand Up @@ -70,6 +71,7 @@ export function SwapForm() {
const finalRefTokenOut = useRef(null)
const isMounted = useIsMounted()
const { isConnected } = useUserAccount()
const { startTokenPricePolling } = useTokens()

const isLoadingSwaps = simulationQuery.isLoading
const isLoading = isLoadingSwaps || !isMounted
Expand Down Expand Up @@ -98,7 +100,11 @@ export function SwapForm() {
}

function onModalClose() {
// restart polling for token prices when modal is closed again
startTokenPricePolling()

previewModalDisclosure.onClose()

if (swapTxHash) {
resetSwapAmounts()
replaceUrlPath()
Expand Down
11 changes: 10 additions & 1 deletion lib/modules/swap/modal/SwapModal.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'

import { Modal, ModalBody, ModalCloseButton, ModalContent, ModalProps } from '@chakra-ui/react'
Expand All @@ -18,6 +19,7 @@ import { useOnUserAccountChanged } from '../../web3/useOnUserAccountChanged'
import { SwapSummary } from './SwapSummary'
import { useSwapReceipt } from '../../transactions/transaction-steps/receipts/receipt.hooks'
import { useUserAccount } from '../../web3/UserAccountProvider'
import { useTokens } from '../../tokens/TokensProvider'

type Props = {
isOpen: boolean
Expand All @@ -35,6 +37,7 @@ export function SwapPreviewModal({
const { isDesktop } = useBreakpoints()
const initialFocusRef = useRef(null)
const { userAddress } = useUserAccount()
const { stopTokenPricePolling } = useTokens()

const { transactionSteps, swapAction, isWrap, selectedChain, swapTxHash, hasQuoteContext } =
useSwap()
Expand All @@ -51,9 +54,15 @@ export function SwapPreviewModal({
if (!isWrap && swapTxHash && !window.location.pathname.includes(swapTxHash)) {
window.history.pushState({}, '', `/swap/${chainToSlugMap[selectedChain]}/${swapTxHash}`)
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [swapTxHash])

useEffect(() => {
if (isOpen) {
// stop polling for token prices when modal is opened to prevent unwanted re-renders
stopTokenPricePolling()
}
}, [isOpen])

useOnUserAccountChanged(onClose)

return (
Expand Down
31 changes: 18 additions & 13 deletions lib/modules/tokens/TokensProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
import { isSameAddress } from '@/lib/shared/utils/addresses'
import { useMandatoryContext } from '@/lib/shared/utils/contexts'
import { bn, Numberish } from '@/lib/shared/utils/numbers'
import { useQuery } from '@apollo/experimental-nextjs-app-support/ssr'
import { useQuery } from '@apollo/client'
import { Dictionary, zipObject } from 'lodash'
import { createContext, PropsWithChildren, useCallback } from 'react'
import { Address } from 'viem'
Expand All @@ -31,24 +31,27 @@ export function _useTokens(
variables: GetTokensQueryVariables
) {
const skipQuery = useSkipInitialQuery(variables)
const pollInterval = mins(3).toMs()

// skip initial fetch on mount so that initialData is used
const { data: tokensData } = useQuery(GetTokensDocument, {
variables,
skip: skipQuery,
})
const { data: tokenPricesData, loading: isLoadingTokenPrices } = useQuery(
GetTokenPricesDocument,
{
variables,
// The server provides us with an initial data set, but we immediately reload the potentially
// stale data to ensure the prices we show are up to date. Every 3 mins, we requery token prices
initialFetchPolicy: 'no-cache',
nextFetchPolicy: 'cache-and-network',
pollInterval: mins(3).toMs(),
notifyOnNetworkStatusChange: true,
}
)
const {
data: tokenPricesData,
loading: isLoadingTokenPrices,
startPolling,
stopPolling,
} = useQuery(GetTokenPricesDocument, {
variables,
// The server provides us with an initial data set, but we immediately reload the potentially
// stale data to ensure the prices we show are up to date. Every 3 mins, we requery token prices
initialFetchPolicy: 'no-cache',
nextFetchPolicy: 'cache-and-network',
pollInterval,
notifyOnNetworkStatusChange: true,
})

const tokens = tokensData?.tokens || initTokenData.tokens
const prices = tokenPricesData?.tokenPrices || initTokenPricesData.tokenPrices
Expand Down Expand Up @@ -153,6 +156,8 @@ export function _useTokens(
usdValueForToken,
calcWeightForBalance,
calcTotalUsdValue,
startTokenPricePolling: () => startPolling(pollInterval),
stopTokenPricePolling: stopPolling,
}
}

Expand Down

0 comments on commit a0282ba

Please sign in to comment.