From e154477e11a8bf10ffafc5b0ebd012659208a485 Mon Sep 17 00:00:00 2001 From: Pearce Date: Thu, 4 Dec 2025 13:39:33 +0100 Subject: [PATCH 01/10] feat: pool alert banner --- .../src/dex/components/PoolAlertBanner.tsx | 39 +++++++++++++++++++ apps/main/src/dex/types/main.types.ts | 2 + 2 files changed, 41 insertions(+) create mode 100644 apps/main/src/dex/components/PoolAlertBanner.tsx diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx new file mode 100644 index 0000000000..ab8941083d --- /dev/null +++ b/apps/main/src/dex/components/PoolAlertBanner.tsx @@ -0,0 +1,39 @@ +import Stack from '@mui/material/Stack' +import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage' +import { ExclamationTriangleIcon } from '@ui-kit/shared/icons/ExclamationTriangleIcon' +import { Banner } from '@ui-kit/shared/ui/Banner' +import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' +import { PoolAlert } from '../types/main.types' + +const { IconSize } = SizesAndSpaces + +const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds + +const PoolAlertBanner = ({ + poolAlert, + poolAlertBannerKey, +}: { + poolAlert: PoolAlert | null + poolAlertBannerKey: string +}) => { + const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) + + if (poolAlert?.banner) + return ( + shouldShowBanner && ( + + + {' '} + {poolAlert.banner.title} + + + ) + ) +} + +export default PoolAlertBanner diff --git a/apps/main/src/dex/types/main.types.ts b/apps/main/src/dex/types/main.types.ts index d0b70ff8cd..9be8453ad7 100644 --- a/apps/main/src/dex/types/main.types.ts +++ b/apps/main/src/dex/types/main.types.ts @@ -5,6 +5,7 @@ import type { IChainId, IDict, INetworkName } from '@curvefi/api/lib/interfaces' import type { PoolTemplate } from '@curvefi/api/lib/pools' import type { TooltipProps } from '@ui/Tooltip/types' import type { BaseConfig } from '@ui/utils' +import { BannerProps } from '@ui-kit/shared/ui/Banner' export type { CurveApi, Wallet } from '@ui-kit/features/connect-wallet' @@ -273,6 +274,7 @@ export interface PoolAlert extends TooltipProps { isInformationOnly?: boolean isInformationOnlyAndShowInForm?: boolean isCloseOnTooltipOnly?: boolean + banner?: Omit & { title: string } isPoolPageOnly?: boolean // Don't show the pools overview table address?: string message: ReactNode From a8f73ab7f23ac04f25b7e91c1ccb581c1ef22e70 Mon Sep 17 00:00:00 2001 From: Pearce Date: Thu, 4 Dec 2025 13:51:49 +0100 Subject: [PATCH 02/10] refactor: replace monad banner alert with pool alert banner --- .../src/dex/components/MonadBannerAlert.tsx | 19 ------------- .../src/dex/components/PagePool/index.tsx | 12 +++++--- .../src/dex/components/PoolAlertBanner.tsx | 28 ++++++++----------- apps/main/src/dex/hooks/usePoolAlert.tsx | 5 ++++ 4 files changed, 24 insertions(+), 40 deletions(-) delete mode 100644 apps/main/src/dex/components/MonadBannerAlert.tsx diff --git a/apps/main/src/dex/components/MonadBannerAlert.tsx b/apps/main/src/dex/components/MonadBannerAlert.tsx deleted file mode 100644 index 2052a63fb3..0000000000 --- a/apps/main/src/dex/components/MonadBannerAlert.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import { Banner } from '@ui-kit/shared/ui/Banner' -import { Stack } from '@mui/material' -import { t } from '@ui-kit/lib/i18n' -import { PoolUrlParams } from '../types/main.types' - -const MonadBannerAlert = ({ params }: { params: PoolUrlParams }) => { - const showFactoryStableNg11Banner = params.pool === 'factory-stable-ng-11' && params.network === 'monad' - - if (showFactoryStableNg11Banner) - return ( - - - {t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`} - - - ) -} - -export default MonadBannerAlert diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx index b27745e184..03920e01b5 100644 --- a/apps/main/src/dex/components/PagePool/index.tsx +++ b/apps/main/src/dex/components/PagePool/index.tsx @@ -20,7 +20,7 @@ import useStore from '@/dex/store/useStore' import { getChainPoolIdActiveKey } from '@/dex/utils' import { getPath } from '@/dex/utils/utilsRouter' import { ManageGauge } from '@/dex/widgets/manage-gauge' -import type { PoolUrlParams } from '@/dex/types/main.types' +import { notFalsy } from '@curvefi/prices-api/objects.util' import Stack from '@mui/material/Stack' import AlertBox from '@ui/AlertBox' import { AppFormContentWrapper } from '@ui/AppForm' @@ -45,7 +45,7 @@ import { t } from '@ui-kit/lib/i18n' import { REFRESH_INTERVAL } from '@ui-kit/lib/model' import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' -import MonadBannerAlert from '../MonadBannerAlert' +import PoolAlertBanner from '../PoolAlertBanner' const DEFAULT_SEED: Seed = { isSeed: null, loaded: false } const { MaxWidth } = SizesAndSpaces @@ -204,10 +204,14 @@ const Transfer = (pageTransferProps: PageTransferProps) => { ) - return ( <> - + {poolAlert?.banner && ( + + )} poolAlertBannerKey: string }) => { const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) - if (poolAlert?.banner) - return ( - shouldShowBanner && ( - - - {' '} - {poolAlert.banner.title} - - - ) + return ( + shouldShowBanner && ( + + + {' '} + {banner.title} + + ) + ) } export default PoolAlertBanner diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx index 9d16b03bd1..919c0f11cb 100644 --- a/apps/main/src/dex/hooks/usePoolAlert.tsx +++ b/apps/main/src/dex/hooks/usePoolAlert.tsx @@ -7,6 +7,7 @@ import Box from '@ui/Box' import { ExternalLink, InternalLink } from '@ui/Link' import { breakpoints } from '@ui/utils' import { useParams } from '@ui-kit/hooks/router' +import { t } from '@ui-kit/lib/i18n' import { shortenAddress } from '@ui-kit/utils' const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { @@ -212,6 +213,10 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { alertType: 'danger', isDisableDeposit: true, isDisableSwap: true, + banner: { + title: t`Misconfigured pool`, + subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`, + }, message: (
This pool is in withdraw only mode, as it has been configured incorrectly.
From a4bc1be7b0de5943e240aea8b5bcbd09c22fd33b Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 10:07:54 +0100 Subject: [PATCH 03/10] feat: implement portal for PoolAlertBanner and update GlobalLayout for rendering --- .../src/dex/components/PoolAlertBanner.tsx | 28 ++++++++++--------- apps/main/src/routes/GlobalLayout.tsx | 2 ++ .../curve-ui-kit/src/shared/ui/Banner.tsx | 2 +- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx index e8559dd05e..3822b2cd7d 100644 --- a/apps/main/src/dex/components/PoolAlertBanner.tsx +++ b/apps/main/src/dex/components/PoolAlertBanner.tsx @@ -1,11 +1,10 @@ -import Stack from '@mui/material/Stack' +import { useEffect, useState } from 'react' +import { createPortal } from 'react-dom' import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage' -import { ExclamationTriangleIcon } from '@ui-kit/shared/icons/ExclamationTriangleIcon' import { Banner } from '@ui-kit/shared/ui/Banner' -import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' import { PoolAlert } from '../types/main.types' -const { IconSize } = SizesAndSpaces +export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal' const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds @@ -17,17 +16,20 @@ const PoolAlertBanner = ({ poolAlertBannerKey: string }) => { const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) + const [portalEl, setPortalEl] = useState(null) - return ( - shouldShowBanner && ( - - - {' '} - {banner.title} - - - ) + useEffect(() => { + setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID)) + }, []) + + const content = ( + + {banner.title} + ) + + if (!shouldShowBanner) return null + return portalEl ? createPortal(content, portalEl) : content } export default PoolAlertBanner diff --git a/apps/main/src/routes/GlobalLayout.tsx b/apps/main/src/routes/GlobalLayout.tsx index 093def2e0e..169dd9b9d1 100644 --- a/apps/main/src/routes/GlobalLayout.tsx +++ b/apps/main/src/routes/GlobalLayout.tsx @@ -1,5 +1,6 @@ import { type ReactNode } from 'react' import daoNetworks from '@/dao/networks' +import { DEX_POOL_ALERT_BANNER_PORTAL_ID } from '@/dex/components/PoolAlertBanner' import { useDexAppStats, useDexRoutes } from '@/dex/hooks/useDexAppStats' import lendNetworks from '@/lend/networks' import { useLlamalendAppStats } from '@/llamalend/hooks/useLlamalendAppStats' @@ -80,6 +81,7 @@ export const GlobalLayout = ({ appStats={useAppStats(currentApp, network)} routes={useAppRoutes(network)} /> + {currentApp === 'dex' && } - + {BannerIcons[icon]} {children} From a4a52c0c06315edc17e6dc672937e122b3394225 Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 12:49:56 +0100 Subject: [PATCH 04/10] refactor: pool alerts splitted into pool banner maessage and user action messaged --- .../src/dex/components/PagePool/index.tsx | 1 + .../src/dex/components/PoolAlertBanner.tsx | 19 +- .../dex/components/pool-alert-messages.tsx | 49 +++++ apps/main/src/dex/hooks/usePoolAlert.tsx | 206 +++++++++--------- apps/main/src/dex/types/main.types.ts | 4 +- 5 files changed, 171 insertions(+), 108 deletions(-) create mode 100644 apps/main/src/dex/components/pool-alert-messages.tsx diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx index cf466de425..e05d96ae37 100644 --- a/apps/main/src/dex/components/PagePool/index.tsx +++ b/apps/main/src/dex/components/PagePool/index.tsx @@ -209,6 +209,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => { <> {poolAlert?.banner && ( diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx index 3822b2cd7d..6200c0d968 100644 --- a/apps/main/src/dex/components/PoolAlertBanner.tsx +++ b/apps/main/src/dex/components/PoolAlertBanner.tsx @@ -1,19 +1,30 @@ import { useEffect, useState } from 'react' import { createPortal } from 'react-dom' import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage' -import { Banner } from '@ui-kit/shared/ui/Banner' -import { PoolAlert } from '../types/main.types' +import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner' +import { AlertType, PoolAlert } from '../types/main.types' export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal' const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds +/** Maps AlertType to BannerSeverity */ +const alertTypeToBannerSeverity: Record = { + error: 'alert', + danger: 'alert', + warning: 'warning', + info: 'info', + '': 'info', +} + const PoolAlertBanner = ({ banner, poolAlertBannerKey, + alertType, }: { banner: NonNullable poolAlertBannerKey: string + alertType: AlertType }) => { const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) const [portalEl, setPortalEl] = useState(null) @@ -22,8 +33,10 @@ const PoolAlertBanner = ({ setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID)) }, []) + const severity = alertTypeToBannerSeverity[alertType] + const content = ( - + {banner.title} ) diff --git a/apps/main/src/dex/components/pool-alert-messages.tsx b/apps/main/src/dex/components/pool-alert-messages.tsx new file mode 100644 index 0000000000..c689353888 --- /dev/null +++ b/apps/main/src/dex/components/pool-alert-messages.tsx @@ -0,0 +1,49 @@ +import Button from '@mui/material/Button' +import Link from '@mui/material/Link' +import Stack from '@mui/material/Stack' +import { ArrowTopRightIcon } from '@ui-kit/shared/icons/ArrowTopRightIcon' +import { RouterLink } from '@ui-kit/shared/ui/RouterLink' +import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' + +const { Spacing } = SizesAndSpaces + +export const MessageWrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + +) + +export const ExternalLink = ({ href, children }: { href: string; children: React.ReactNode }) => ( + +) + +export const InternalLink = ({ href, children }: { href: string; children: React.ReactNode }) => ( + +) diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx index 4d98648789..521adf5709 100644 --- a/apps/main/src/dex/hooks/usePoolAlert.tsx +++ b/apps/main/src/dex/hooks/usePoolAlert.tsx @@ -1,14 +1,10 @@ import { useMemo } from 'react' -import { styled } from 'styled-components' import { ROUTE } from '@/dex/constants' import { PoolAlert, PoolData, PoolDataCache, type UrlParams } from '@/dex/types/main.types' -import { getPath } from '@/dex/utils/utilsRouter' -import Box from '@ui/Box' -import { ExternalLink, InternalLink } from '@ui/Link' -import { breakpoints } from '@ui/utils' import { useParams } from '@ui-kit/hooks/router' -import { t } from '@ui-kit/lib/i18n' -import { shortenAddress } from '@ui-kit/utils' +import { t, Trans } from '@ui-kit/lib/i18n' +import { getInternalUrl } from '@ui-kit/shared/routes' +import { ExternalLink, InternalLink, MessageWrapper } from '../components/pool-alert-messages' const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { const params = useParams() @@ -23,15 +19,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableDeposit: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`zStables Attack`, + subtitle: t`zStables (zETH, UZD) have encountered an attack. `, + learnMoreUrl: 'https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20', + }, message: ( -
- zStables (zETH, UZD) have encountered an attack. The collateral remain secure, we delve into the ongoing - investigation. —Zunami Protocol{' '} - - https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20 - -
+

{t`Deposit disabled.`}

), }) @@ -41,21 +36,23 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableSwap: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`Geist Finance Disabled`, + subtitle: t`Deposit and swap are disabled.`, + learnMoreUrl: 'https://twitter.com/geistfinance', + }, message: ( -
- Deposit and swap are disabled, see{' '} - - https://twitter.com/geistfinance - {' '} - for additional information. -
+

{t`This pool is in withdraw only mode.`}

), }) const yPrismaAlert = (): PoolAlert => { - const redirectPathname = params && getPath(params, `${ROUTE.PAGE_POOLS}/factory-v2-372${ROUTE.PAGE_POOL_DEPOSIT}`) - const redirectText = `PRISMA/yPRISMA pool (${shortenAddress('0x69833361991ed76f9e8dbbcdf9ea1520febfb4a7')})` + const prismaPoolHref = getInternalUrl( + 'dex', + params.network, + `${ROUTE.PAGE_POOLS}/factory-v2-372${ROUTE.PAGE_POOL_DEPOSIT}`, + ) return { isDisableDeposit: true, isInformationOnly: true, @@ -63,19 +60,18 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { alertType: 'warning', message: ( -
- This pool has been deprecated. Please use the{' '} - {redirectPathname ? ( - - {redirectText} - - ) : ( - {redirectText} - )}{' '} - instead. -
+

{t`Deposit disabled.`}

), + banner: { + title: t`Deprecated Pool`, + subtitle: ( + + This pool has been deprecated. Please use the{' '} + PRISMA/yPRISMA pool instead. + + ), + }, } } const synthetixAlert = (): PoolAlert => ({ @@ -83,28 +79,34 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isInformationOnly: true, isCloseOnTooltipOnly: true, minWidth: '350px', + banner: { + title: t`Synthetix Synths Disabled`, + subtitle: t`Exchanges on Synthetix synths are expected to be disabled. Users should withdraw liquidity or redeem synths to sUSD. Exit pools to avoid value dilution.`, + learnMoreUrl: 'https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2', + }, message: ( - -

+

+ Please note that exchanges on synthetix synths are expected to be disabled and users can either withdraw liquidity from the underlying token, or redeem their synths to sUSD on{' '} - - https://staking.synthetix.io/wallet/balances/ - -

-

+ synthetix.io + +

+

+ Users are encouraged to exit the pools in order to avoid getting their holdings‘ value diluted with the discountRate For more information please refer to{' '} - - https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2 + + gov.curve.finance -

-

Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ...

-
+ +

+

+ + Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ... + +

), }) @@ -112,9 +114,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { alertType: 'warning', isInformationOnlyAndShowInForm: true, isDisableDeposit: true, + banner: { + title: t`Ironbank Protocol Deprecated`, + subtitle: t`The Ironbank protocol is deprecated. Please do not supply liquidity to this pool.`, + }, message: ( -
Ironbank protocol is deprecated. Please do not supply liquidity to this pool.
+

{t`Deposit disabled.`}

), }) @@ -124,15 +130,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableSwap: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`Synthetix USD Deprecated`, + subtitle: t`Pool is deprecated. Deposit and swap are disabled.`, + learnMoreUrl: 'https://x.com/synthetix_io/status/1953054538610688198', + }, message: ( -
- Deposit and swap are disabled, see{' '} - - https://x.com/synthetix_io/status/1953054538610688198 - {' '} - for additional information. -
+

{t`This pool is in withdraw only mode.`}

), }) @@ -141,16 +146,22 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableDeposit: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`YieldBasis Managed Pool`, + subtitle: ( + + This pool is managed by YieldBasis. Only deposits made on the YieldBasis UI earn fees and rewards. + + ), + learnMoreUrl: 'https://yieldbasis.com', + }, message: ( -
- This pool is managed by YieldBasis. Only deposits made on the YieldBasis UI earn fees and rewards.{' '} -
Go to{' '} - - yieldbasis.com - {' '} - to deposit. -
+

+ + Deposit on yieldbasis.com + +

), }) @@ -160,9 +171,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableDeposit: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`USPD Exploited`, + subtitle: t`USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.`, + }, message: ( -
USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.
+

{t`Deposit disabled. We recommend exiting this pool.`}

), }) @@ -174,12 +189,12 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isInformationOnlyAndShowInForm: true, message: ( -
- Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '} - - More details - -
+

+ + Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '} + More details + +

), }) @@ -190,32 +205,31 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isDisableDeposit: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`Vyper Vulnerability Exploit`, + subtitle: t`This pool has been exploited due to a vulnerability found in Vyper versions v0.2.15, v0.2.16, or v0.3.0.`, + learnMoreUrl: 'https://hackmd.io/@LlamaRisk/BJzSKHNjn', + }, message: ( -
- This pool has been exploited due to a vulnerability found in Vyper versions v0.2.15, v0.2.16, or v0.3.0. For - additional information, please click on the post-mortem link:{' '} - - https://hackmd.io/@LlamaRisk/BJzSKHNjn - -
+

{t`Deposit disabled. We recommend exiting this pool.`}

), }) + const possibleVyperExploitedAlert = (): PoolAlert => ({ alertType: 'danger', isDisableDeposit: true, isInformationOnly: true, isCloseOnTooltipOnly: true, + banner: { + title: t`Potential Vulnerability Exploit`, + subtitle: t`This pool might be at risk of being exploited. We recommend exiting this pool.`, + learnMoreUrl: 'https://twitter.com/CurveFinance/status/1685925429041917952', + }, message: ( -
- This pool might be at risk of being exploited. While security researchers have not identified a profitable - exploit, we recommend exiting this pool.{' '} - - https://twitter.com/CurveFinance/status/1685925429041917952 - -
+

{t`Deposit disabled. We recommend exiting this pool.`}

), }) @@ -229,12 +243,12 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isInformationOnlyAndShowInForm: true, isCloseOnTooltipOnly: true, banner: { - title: t`Misconfigured pool`, + title: t`Misconfigured Pool`, subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`, }, message: ( -
This pool has been badly configured and is in withdraw only mode.
+

{t`This pool is in withdraw only mode.`}

), }) @@ -263,7 +277,6 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { '0xd9ff8396554a0d18b2cfbec53e1979b7ecce8373': yieldbasisAlert(), '0x06cf5f9b93e9fcfdb33d6b3791eb152567cd8d36': uspdioAlert(), - // arbitrum '0x960ea3e3c7fb317332d990873d354e18d7645590': possibleVyperExploitedAlert(), // tricrypto @@ -285,19 +298,4 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { }, [poolAddress, params, hasVyperVulnerability]) } -const MessageWrapper = styled.div` - align-items: flex-start; - display: flex; - flex-direction: column; - - a { - word-break: break-word; - } - - @media (min-width: ${breakpoints.sm}rem) { - align-items: center; - flex-direction: row; - } -` - export default usePoolAlert diff --git a/apps/main/src/dex/types/main.types.ts b/apps/main/src/dex/types/main.types.ts index b003057498..67528c347b 100644 --- a/apps/main/src/dex/types/main.types.ts +++ b/apps/main/src/dex/types/main.types.ts @@ -274,10 +274,12 @@ export interface PoolAlert extends TooltipProps { isInformationOnly?: boolean isInformationOnlyAndShowInForm?: boolean isCloseOnTooltipOnly?: boolean + // banner message, related to the market situation banner?: Omit & { title: string } isPoolPageOnly?: boolean // Don't show the pools overview table address?: string - message: ReactNode + // action card message, related to action of user + message?: ReactNode } export type EstimatedGas = number | number[] | null From d1fa633fd7e54cbe14ea66967a9b8f7a34ae80bf Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 14:00:42 +0100 Subject: [PATCH 05/10] fix: ensure pool alerts display messages only when present --- .../PagePool/Deposit/components/FormDeposit.tsx | 2 +- .../PagePool/Deposit/components/FormDepositStake.tsx | 2 +- .../main/src/dex/components/PagePool/Deposit/index.tsx | 2 +- .../PagePool/PoolDetails/PoolStats/index.tsx | 6 ++++-- apps/main/src/dex/components/PagePool/Swap/index.tsx | 2 +- apps/main/src/dex/components/PagePool/index.tsx | 2 +- apps/main/src/dex/components/PoolLabel.tsx | 10 ++++++---- apps/main/src/dex/hooks/usePoolAlert.tsx | 1 + 8 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx index 563f47e5b0..5e5caa7cef 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx @@ -298,7 +298,7 @@ const FormDeposit = ({ /> - {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx index de10456eaa..35a943abc2 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx @@ -298,7 +298,7 @@ const FormDepositStake = ({ /> - {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/Deposit/index.tsx b/apps/main/src/dex/components/PagePool/Deposit/index.tsx index e6f2ae2571..8b7b0e52b1 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/index.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/index.tsx @@ -51,7 +51,7 @@ const Deposit = ({ hasDepositAndStake, ...transferProps }: TransferProps & { has {poolAlert && poolAlert.isDisableDeposit ? ( - {poolAlert.message} + poolAlert.message && {poolAlert.message} ) : ( <> {formType === 'DEPOSIT' && } diff --git a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx index 03f1608d70..c6e94e18a5 100644 --- a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx +++ b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx @@ -46,10 +46,12 @@ const PoolStats = ({ curve, routerParams, poolAlert, poolData, poolDataCacheOrAp {poolData && } - {poolAlert && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && ( + {poolAlert?.message && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} - {tokenAlert && tokenAlert.isInformationOnly && {tokenAlert.message}} + {tokenAlert?.message && tokenAlert.isInformationOnly && ( + {tokenAlert.message} + )} {poolDataCacheOrApi.pool.referenceAsset === 'CRYPTO' && ( diff --git a/apps/main/src/dex/components/PagePool/Swap/index.tsx b/apps/main/src/dex/components/PagePool/Swap/index.tsx index 37821669b1..e6655b17ef 100644 --- a/apps/main/src/dex/components/PagePool/Swap/index.tsx +++ b/apps/main/src/dex/components/PagePool/Swap/index.tsx @@ -642,7 +642,7 @@ const Swap = ({ - {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx index e05d96ae37..690d324244 100644 --- a/apps/main/src/dex/components/PagePool/index.tsx +++ b/apps/main/src/dex/components/PagePool/index.tsx @@ -234,7 +234,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => { {rFormType === 'swap' ? ( {poolAlert?.isDisableSwap ? ( - {poolAlert.message} + poolAlert.message && {poolAlert.message} ) : ( {!isMobile && ( <> - {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && ( + {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && poolAlert?.message && ( {poolAlert.message} )} - {tokenAlert && ( + {tokenAlert?.message && ( {tokenAlert.message} @@ -119,8 +119,10 @@ const PoolLabel = ({ className = '', blockchainId, isVisible = true, poolData, q
- {tokenAlert && isMobile && {tokenAlert.message}} - {poolAlert && !poolAlert.isPoolPageOnly && ( + {tokenAlert?.message && isMobile && ( + {tokenAlert.message} + )} + {poolAlert && poolAlert.message && !poolAlert.isPoolPageOnly && ( <> {!poolAlert.isInformationOnly && !poolAlert.isInformationOnlyAndShowInForm ? ( {poolAlert.message} diff --git a/apps/main/src/dex/hooks/usePoolAlert.tsx b/apps/main/src/dex/hooks/usePoolAlert.tsx index 521adf5709..fe85ed7929 100644 --- a/apps/main/src/dex/hooks/usePoolAlert.tsx +++ b/apps/main/src/dex/hooks/usePoolAlert.tsx @@ -24,6 +24,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { subtitle: t`zStables (zETH, UZD) have encountered an attack. `, learnMoreUrl: 'https://twitter.com/ZunamiProtocol/status/1690863406079696896?s=20', }, + /* TODO: use Typography component instead of p tag */ message: (

{t`Deposit disabled.`}

From 9ec9dfd9c811cb57642e377191d8576acbeca38b Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 16:59:04 +0100 Subject: [PATCH 06/10] Revert "fix: ensure pool alerts display messages only when present" This reverts commit d1fa633fd7e54cbe14ea66967a9b8f7a34ae80bf. --- .../PagePool/Deposit/components/FormDeposit.tsx | 2 +- .../PagePool/Deposit/components/FormDepositStake.tsx | 2 +- .../main/src/dex/components/PagePool/Deposit/index.tsx | 2 +- .../PagePool/PoolDetails/PoolStats/index.tsx | 6 ++---- apps/main/src/dex/components/PagePool/Swap/index.tsx | 2 +- apps/main/src/dex/components/PagePool/index.tsx | 2 +- apps/main/src/dex/components/PoolLabel.tsx | 10 ++++------ 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx index 5e5caa7cef..563f47e5b0 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDeposit.tsx @@ -298,7 +298,7 @@ const FormDeposit = ({ /> - {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx index 35a943abc2..de10456eaa 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/components/FormDepositStake.tsx @@ -298,7 +298,7 @@ const FormDepositStake = ({ /> - {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/Deposit/index.tsx b/apps/main/src/dex/components/PagePool/Deposit/index.tsx index 8b7b0e52b1..e6f2ae2571 100644 --- a/apps/main/src/dex/components/PagePool/Deposit/index.tsx +++ b/apps/main/src/dex/components/PagePool/Deposit/index.tsx @@ -51,7 +51,7 @@ const Deposit = ({ hasDepositAndStake, ...transferProps }: TransferProps & { has {poolAlert && poolAlert.isDisableDeposit ? ( - poolAlert.message && {poolAlert.message} + {poolAlert.message} ) : ( <> {formType === 'DEPOSIT' && } diff --git a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx index c6e94e18a5..03f1608d70 100644 --- a/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx +++ b/apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/index.tsx @@ -46,12 +46,10 @@ const PoolStats = ({ curve, routerParams, poolAlert, poolData, poolDataCacheOrAp {poolData && } - {poolAlert?.message && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && ( + {poolAlert && !poolAlert.isDisableDeposit && !poolAlert.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} - {tokenAlert?.message && tokenAlert.isInformationOnly && ( - {tokenAlert.message} - )} + {tokenAlert && tokenAlert.isInformationOnly && {tokenAlert.message}} {poolDataCacheOrApi.pool.referenceAsset === 'CRYPTO' && ( diff --git a/apps/main/src/dex/components/PagePool/Swap/index.tsx b/apps/main/src/dex/components/PagePool/Swap/index.tsx index e6655b17ef..37821669b1 100644 --- a/apps/main/src/dex/components/PagePool/Swap/index.tsx +++ b/apps/main/src/dex/components/PagePool/Swap/index.tsx @@ -642,7 +642,7 @@ const Swap = ({ - {poolAlert?.message && poolAlert?.isInformationOnlyAndShowInForm && ( + {poolAlert && poolAlert?.isInformationOnlyAndShowInForm && ( {poolAlert.message} )} diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx index 690d324244..e05d96ae37 100644 --- a/apps/main/src/dex/components/PagePool/index.tsx +++ b/apps/main/src/dex/components/PagePool/index.tsx @@ -234,7 +234,7 @@ const Transfer = (pageTransferProps: PageTransferProps) => { {rFormType === 'swap' ? ( {poolAlert?.isDisableSwap ? ( - poolAlert.message && {poolAlert.message} + {poolAlert.message} ) : ( {!isMobile && ( <> - {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && poolAlert?.message && ( + {(poolAlert?.isInformationOnly || poolAlert?.isInformationOnlyAndShowInForm) && ( {poolAlert.message} )} - {tokenAlert?.message && ( + {tokenAlert && ( {tokenAlert.message} @@ -119,10 +119,8 @@ const PoolLabel = ({ className = '', blockchainId, isVisible = true, poolData, q
- {tokenAlert?.message && isMobile && ( - {tokenAlert.message} - )} - {poolAlert && poolAlert.message && !poolAlert.isPoolPageOnly && ( + {tokenAlert && isMobile && {tokenAlert.message}} + {poolAlert && !poolAlert.isPoolPageOnly && ( <> {!poolAlert.isInformationOnly && !poolAlert.isInformationOnlyAndShowInForm ? ( {poolAlert.message} From fda0c3ad6373e592cde96cdec34aee97e6077f8a Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 17:39:24 +0100 Subject: [PATCH 07/10] fix: ensure AlertBox display messages only when present --- packages/ui/src/AlertBox/AlertBox.tsx | 78 ++++++++++++++------------- 1 file changed, 40 insertions(+), 38 deletions(-) diff --git a/packages/ui/src/AlertBox/AlertBox.tsx b/packages/ui/src/AlertBox/AlertBox.tsx index be5f833918..20430ffb94 100644 --- a/packages/ui/src/AlertBox/AlertBox.tsx +++ b/packages/ui/src/AlertBox/AlertBox.tsx @@ -33,45 +33,47 @@ const AlertBox = ({ className, alertType, children, title, limitHeight, handleBt }, [children, limitHeight]) return ( - - {title ? ( - <> -
- {IconComp} {title}{' '} -
- {showFullHeight ? children : cutAlert} - - ) : ( - - {IconComp} - + (title || children) && ( + + {title ? ( + <> +
+ {IconComp} {title}{' '} +
{showFullHeight ? children : cutAlert} -
- {handleBtnClose !== undefined && ( - - - - )} -
- )} - {limitHeight && enabledHeightToggle && ( - - - setShowFullHeight(!showFullHeight)}> - {showFullHeight ? 'Minimize' : 'Expand'} - {showFullHeight ? : } - - - - )} -
+ + ) : ( + + {IconComp} + + {showFullHeight ? children : cutAlert} + + {handleBtnClose !== undefined && ( + + + + )} + + )} + {limitHeight && enabledHeightToggle && ( + + + setShowFullHeight(!showFullHeight)}> + {showFullHeight ? 'Minimize' : 'Expand'} + {showFullHeight ? : } + + + + )} + + ) ) } From d9d755ea14ad0f414fafc9c4cd5fa8f6bf9a9ea4 Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 17:40:32 +0100 Subject: [PATCH 08/10] refactor: update PoolAlertBanner to use useMemo for portal target and export component --- .../src/dex/components/PagePool/index.tsx | 2 +- .../src/dex/components/PoolAlertBanner.tsx | 31 +++++++------------ apps/main/src/routes/GlobalLayout.tsx | 2 -- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/apps/main/src/dex/components/PagePool/index.tsx b/apps/main/src/dex/components/PagePool/index.tsx index e05d96ae37..76d69cf8ac 100644 --- a/apps/main/src/dex/components/PagePool/index.tsx +++ b/apps/main/src/dex/components/PagePool/index.tsx @@ -46,7 +46,7 @@ import { t } from '@ui-kit/lib/i18n' import { REFRESH_INTERVAL } from '@ui-kit/lib/model' import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' -import PoolAlertBanner from '../PoolAlertBanner' +import { PoolAlertBanner } from '../PoolAlertBanner' const DEFAULT_SEED: Seed = { isSeed: null, loaded: false } const { MaxWidth } = SizesAndSpaces diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx index 6200c0d968..1c80f4c343 100644 --- a/apps/main/src/dex/components/PoolAlertBanner.tsx +++ b/apps/main/src/dex/components/PoolAlertBanner.tsx @@ -1,11 +1,9 @@ -import { useEffect, useState } from 'react' +import { useMemo } from 'react' import { createPortal } from 'react-dom' import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage' import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner' import { AlertType, PoolAlert } from '../types/main.types' -export const DEX_POOL_ALERT_BANNER_PORTAL_ID = 'dex-pool-alert-banner-portal' - const ONE_DAY_MS = 24 * 60 * 60 * 1000 // 24 hours in milliseconds /** Maps AlertType to BannerSeverity */ @@ -17,7 +15,7 @@ const alertTypeToBannerSeverity: Record = { '': 'info', } -const PoolAlertBanner = ({ +export const PoolAlertBanner = ({ banner, poolAlertBannerKey, alertType, @@ -27,22 +25,17 @@ const PoolAlertBanner = ({ alertType: AlertType }) => { const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) - const [portalEl, setPortalEl] = useState(null) - - useEffect(() => { - setPortalEl(document.getElementById(DEX_POOL_ALERT_BANNER_PORTAL_ID)) - }, []) - + const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], []) const severity = alertTypeToBannerSeverity[alertType] - const content = ( - - {banner.title} - + return ( + shouldShowBanner && + portalTarget && + createPortal( + + {banner.title} + , + portalTarget, + ) ) - - if (!shouldShowBanner) return null - return portalEl ? createPortal(content, portalEl) : content } - -export default PoolAlertBanner diff --git a/apps/main/src/routes/GlobalLayout.tsx b/apps/main/src/routes/GlobalLayout.tsx index 169dd9b9d1..093def2e0e 100644 --- a/apps/main/src/routes/GlobalLayout.tsx +++ b/apps/main/src/routes/GlobalLayout.tsx @@ -1,6 +1,5 @@ import { type ReactNode } from 'react' import daoNetworks from '@/dao/networks' -import { DEX_POOL_ALERT_BANNER_PORTAL_ID } from '@/dex/components/PoolAlertBanner' import { useDexAppStats, useDexRoutes } from '@/dex/hooks/useDexAppStats' import lendNetworks from '@/lend/networks' import { useLlamalendAppStats } from '@/llamalend/hooks/useLlamalendAppStats' @@ -81,7 +80,6 @@ export const GlobalLayout = ({ appStats={useAppStats(currentApp, network)} routes={useAppRoutes(network)} /> - {currentApp === 'dex' && } Date: Tue, 16 Dec 2025 17:56:26 +0100 Subject: [PATCH 09/10] refactor: rename MessageWrapper to PoolAlertMessage and update usage in usePoolAlert hook --- .../dex/components/pool-alert-messages.tsx | 2 +- apps/main/src/dex/hooks/usePoolAlert.tsx | 50 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/apps/main/src/dex/components/pool-alert-messages.tsx b/apps/main/src/dex/components/pool-alert-messages.tsx index c689353888..667dfdeb69 100644 --- a/apps/main/src/dex/components/pool-alert-messages.tsx +++ b/apps/main/src/dex/components/pool-alert-messages.tsx @@ -7,7 +7,7 @@ import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' const { Spacing } = SizesAndSpaces -export const MessageWrapper = ({ children }: { children: React.ReactNode }) => ( +export const PoolAlertMessage = ({ children }: { children: React.ReactNode }) => ( { const params = useParams() @@ -26,9 +26,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { }, /* TODO: use Typography component instead of p tag */ message: ( - +

{t`Deposit disabled.`}

-
+ ), }) const geistFinanceAlert = (): PoolAlert => ({ @@ -43,9 +43,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://twitter.com/geistfinance', }, message: ( - +

{t`This pool is in withdraw only mode.`}

-
+ ), }) const yPrismaAlert = (): PoolAlert => { @@ -60,9 +60,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isCloseOnTooltipOnly: true, alertType: 'warning', message: ( - +

{t`Deposit disabled.`}

-
+ ), banner: { title: t`Deprecated Pool`, @@ -86,7 +86,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://gov.curve.finance/t/kill-gauges-on-all-non-susd-curve-pools-on-ethereum/10033/2', }, message: ( - +

Please note that exchanges on synthetix synths are expected to be disabled and users can either withdraw @@ -108,7 +108,7 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { Please note that sUSD is not involved, so these would be on the other pools sETH, sBTC, sForex ...

-
+ ), }) const ironbankAlert = (): PoolAlert => ({ @@ -120,9 +120,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { subtitle: t`The Ironbank protocol is deprecated. Please do not supply liquidity to this pool.`, }, message: ( - +

{t`Deposit disabled.`}

-
+ ), }) const synthetixUsdAlert = (): PoolAlert => ({ @@ -137,9 +137,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://x.com/synthetix_io/status/1953054538610688198', }, message: ( - +

{t`This pool is in withdraw only mode.`}

-
+ ), }) const yieldbasisAlert = (): PoolAlert => ({ @@ -157,13 +157,13 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://yieldbasis.com', }, message: ( - +

Deposit on yieldbasis.com

-
+ ), }) @@ -177,9 +177,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { subtitle: t`USPD has been exploited. This pool has been disabled to prevent new users from loss of funds.`, }, message: ( - +

{t`Deposit disabled. We recommend exiting this pool.`}

-
+ ), }) @@ -189,14 +189,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { isCloseOnTooltipOnly: true, isInformationOnlyAndShowInForm: true, message: ( - +

Deposit and Swap with wBTC.e will return an error due to an Aave community decision to freeze this asset.{' '} More details

-
+ ), }) @@ -212,9 +212,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://hackmd.io/@LlamaRisk/BJzSKHNjn', }, message: ( - +

{t`Deposit disabled. We recommend exiting this pool.`}

-
+ ), }) @@ -229,9 +229,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { learnMoreUrl: 'https://twitter.com/CurveFinance/status/1685925429041917952', }, message: ( - +

{t`Deposit disabled. We recommend exiting this pool.`}

-
+ ), }) @@ -248,9 +248,9 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => { subtitle: t`This pool has been misconfigured. It has been set to withdraw only. To minimize impact withdraw in balanced proportion instead of single sided.`, }, message: ( - +

{t`This pool is in withdraw only mode.`}

-
+ ), }) From 1acfd5d6d50bb086f5854dcd248c70cc667b2b8b Mon Sep 17 00:00:00 2001 From: Pearce Date: Tue, 16 Dec 2025 17:56:31 +0100 Subject: [PATCH 10/10] fix: re-render pool alert banner on breakpoint change --- apps/main/src/dex/components/PoolAlertBanner.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/main/src/dex/components/PoolAlertBanner.tsx b/apps/main/src/dex/components/PoolAlertBanner.tsx index 1c80f4c343..a1033087a2 100644 --- a/apps/main/src/dex/components/PoolAlertBanner.tsx +++ b/apps/main/src/dex/components/PoolAlertBanner.tsx @@ -1,5 +1,6 @@ import { useMemo } from 'react' import { createPortal } from 'react-dom' +import { useIsDesktop } from '@ui-kit/hooks/useBreakpoints' import { useDismissBanner } from '@ui-kit/hooks/useLocalStorage' import { Banner, BannerProps } from '@ui-kit/shared/ui/Banner' import { AlertType, PoolAlert } from '../types/main.types' @@ -25,7 +26,9 @@ export const PoolAlertBanner = ({ alertType: AlertType }) => { const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS) - const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], []) + const isDesktop = useIsDesktop() + // eslint-disable-next-line react-hooks/exhaustive-deps -- isDesktop triggers re-query when header changes (desktop ↔ mobile) + const portalTarget = useMemo(() => document.getElementsByTagName('header')[0], [isDesktop]) const severity = alertTypeToBannerSeverity[alertType] return (