diff --git a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts index 66d35add69..9fe741c9d1 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/state/usdRawPricesAtom.ts @@ -13,31 +13,51 @@ export interface UsdRawPriceState { export type UsdRawPrices = { [tokenAddress: string]: UsdRawPriceState } +const usdPriceQueueSubscribersCountAtom = atom<{ [tokenAddress: string]: number }>({}) + export const currenciesUsdPriceQueueAtom = atom<{ [tokenAddress: string]: Token }>({}) export const usdRawPricesAtom = atom({}) -export const addCurrencyToUsdPriceQueue = atom(null, (get, set, currency: Token) => { - const currencyAddress = currency.address.toLowerCase() - const currenciesToLoadUsdPrice = get(currenciesUsdPriceQueueAtom) +export const addCurrencyToUsdPriceQueue = atom(null, (get, set, token: Token) => { + const currencyAddress = token.address.toLowerCase() + const usdPriceQueueSubscribersCount = get(usdPriceQueueSubscribersCountAtom) + const currenciesToLoadUsdPrice = { ...get(currenciesUsdPriceQueueAtom) } + + const subscribersCount = (usdPriceQueueSubscribersCount[currencyAddress] || 0) + 1 + + // Increase the subscribers count + set(usdPriceQueueSubscribersCountAtom, { + ...usdPriceQueueSubscribersCount, + [currencyAddress]: subscribersCount, + }) if (!currenciesToLoadUsdPrice[currencyAddress]) { set(currenciesUsdPriceQueueAtom, { ...currenciesToLoadUsdPrice, - [currencyAddress]: currency, + [currencyAddress]: token, }) } }) -export const removeCurrencyToUsdPriceFromQueue = atom(null, (get, set, currency: Token) => { - const currencyAddress = currency.address.toLowerCase() - const currenciesToLoadUsdPrice = get(currenciesUsdPriceQueueAtom) +export const removeCurrencyToUsdPriceFromQueue = atom(null, (get, set, token: Token) => { + const currencyAddress = token.address.toLowerCase() + const usdPriceQueueSubscribersCount = get(usdPriceQueueSubscribersCountAtom) + const currenciesToLoadUsdPrice = { ...get(currenciesUsdPriceQueueAtom) } + + const subscribersCount = Math.max((usdPriceQueueSubscribersCount[currencyAddress] || 0) - 1, 0) + + // Decrease the subscribers count + set(usdPriceQueueSubscribersCountAtom, { + ...usdPriceQueueSubscribersCount, + [currencyAddress]: subscribersCount, + }) - if (currenciesToLoadUsdPrice[currencyAddress]) { - const stateCopy = { ...currenciesToLoadUsdPrice } - delete stateCopy[currencyAddress] + // If there are no subscribers, then delete the token from queue + if (subscribersCount === 0) { + delete currenciesToLoadUsdPrice[currencyAddress] - set(currenciesUsdPriceQueueAtom, stateCopy) + set(currenciesUsdPriceQueueAtom, currenciesToLoadUsdPrice) } }) diff --git a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts index 4be20f6d85..b2dfe59839 100644 --- a/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts +++ b/apps/cowswap-frontend/src/modules/usdAmount/updaters/UsdPricesUpdater.ts @@ -8,6 +8,7 @@ import ms from 'ms.macro' import useSWR, { SWRConfiguration } from 'swr' import { USDC } from 'legacy/constants/tokens' +import useDebounce from 'legacy/hooks/useDebounce' import { useWalletInfo } from 'modules/wallet' @@ -31,6 +32,8 @@ const swrOptions: SWRConfiguration = { revalidateOnFocus: true, } +const USD_PRICES_QUEUE_DEBOUNCE_TIME = ms`0.5s` + export function UsdPricesUpdater() { const { chainId } = useWalletInfo() const setUsdPrices = useSetAtom(usdRawPricesAtom) @@ -40,15 +43,17 @@ export function UsdPricesUpdater() { const queue = useMemo(() => Object.values(currenciesUsdPriceQueue), [currenciesUsdPriceQueue]) + const debouncedQueue = useDebounce(queue, USD_PRICES_QUEUE_DEBOUNCE_TIME) + const swrResponse = useSWR( - ['UsdPricesUpdater', queue, chainId], + ['UsdPricesUpdater', debouncedQueue, chainId], () => { const getUsdcPrice = usdcPriceLoader(chainId) - setUsdPricesLoading(queue) + setUsdPricesLoading(debouncedQueue) - return processQueue(queue, getUsdcPrice).catch((error) => { - resetUsdPrices(queue) + return processQueue(debouncedQueue, getUsdcPrice).catch((error) => { + resetUsdPrices(debouncedQueue) return Promise.reject(error) })