diff --git a/apps/main/src/dex/components/MonadBannerAlert.tsx b/apps/main/src/dex/components/MonadBannerAlert.tsx
deleted file mode 100644
index 7ab1161475..0000000000
--- a/apps/main/src/dex/components/MonadBannerAlert.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { Stack } from '@mui/material'
-import { t } from '@ui-kit/lib/i18n'
-import { Banner } from '@ui-kit/shared/ui/Banner'
-import { Chain } from '@ui-kit/utils'
-import { usePoolIdByAddressOrId } from '../hooks/usePoolIdByAddressOrId'
-
-const MonadBannerAlert = ({ chainId, poolIdOrAddress }: { chainId: number; poolIdOrAddress: string }) => {
- const poolId = usePoolIdByAddressOrId({ chainId, poolIdOrAddress })
- const showFactoryStableNg11Banner = poolId === 'factory-stable-ng-11' && chainId === Chain.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 7f40d4d304..76d69cf8ac 100644
--- a/apps/main/src/dex/components/PagePool/index.tsx
+++ b/apps/main/src/dex/components/PagePool/index.tsx
@@ -21,6 +21,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 { 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 +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 MonadBannerAlert from '../MonadBannerAlert'
+import { PoolAlertBanner } from '../PoolAlertBanner'
const DEFAULT_SEED: Seed = { isSeed: null, loaded: false }
const { MaxWidth } = SizesAndSpaces
@@ -204,10 +205,15 @@ const Transfer = (pageTransferProps: PageTransferProps) => {
)
-
return (
<>
-
+ {poolAlert?.banner && (
+
+ )}
= {
+ error: 'alert',
+ danger: 'alert',
+ warning: 'warning',
+ info: 'info',
+ '': 'info',
+}
+
+export const PoolAlertBanner = ({
+ banner,
+ poolAlertBannerKey,
+ alertType,
+}: {
+ banner: NonNullable
+ poolAlertBannerKey: string
+ alertType: AlertType
+}) => {
+ const { shouldShowBanner, dismissBanner } = useDismissBanner(poolAlertBannerKey, ONE_DAY_MS)
+ 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 (
+ shouldShowBanner &&
+ portalTarget &&
+ createPortal(
+
+ {banner.title}
+ ,
+ portalTarget,
+ )
+ )
+}
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..667dfdeb69
--- /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 PoolAlertMessage = ({ children }: { children: React.ReactNode }) => (
+
+ {children}
+
+)
+
+export const ExternalLink = ({ href, children }: { href: string; children: React.ReactNode }) => (
+ }
+ href={href}
+ target="_blank"
+ rel="noreferrer noopener"
+ >
+ {children}
+
+)
+
+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 eef576711d..8f3953e5f3 100644
--- a/apps/main/src/dex/hooks/usePoolAlert.tsx
+++ b/apps/main/src/dex/hooks/usePoolAlert.tsx
@@ -1,13 +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 { shortenAddress } from '@ui-kit/utils'
+import { t, Trans } from '@ui-kit/lib/i18n'
+import { getInternalUrl } from '@ui-kit/shared/routes'
+import { ExternalLink, InternalLink, PoolAlertMessage } from '../components/pool-alert-messages'
const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
const params = useParams()
@@ -22,16 +19,16 @@ 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',
+ },
+ /* TODO: use Typography component instead of p tag */
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
-
-
- 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 => ({
@@ -82,39 +80,49 @@ 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 ...
+
+
+
),
})
const ironbankAlert = (): PoolAlert => ({
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.
- Deposit and swap are disabled, see{' '}
-
- https://x.com/synthetix_io/status/1953054538610688198
- {' '}
- for additional information.
-
-
+
+
{t`This pool is in withdraw only mode.`}
+
),
})
const yieldbasisAlert = (): PoolAlert => ({
@@ -140,17 +147,23 @@ 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
+
+
+
),
})
@@ -159,10 +172,14 @@ 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.`}
- 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
+
+
+
),
})
@@ -189,33 +206,32 @@ 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.`}
+
),
})
@@ -227,10 +243,14 @@ const usePoolAlert = (poolData?: PoolData | PoolDataCache) => {
isInformationOnly: true,
isInformationOnlyAndShowInForm: true,
isCloseOnTooltipOnly: 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 has been badly configured and is in withdraw only mode.