diff --git a/packages/lib/modules/pool/actions/create/constants.ts b/packages/lib/modules/pool/actions/create/constants.ts
index 537aa937a..c2498b9b1 100644
--- a/packages/lib/modules/pool/actions/create/constants.ts
+++ b/packages/lib/modules/pool/actions/create/constants.ts
@@ -101,6 +101,7 @@ export const INITIAL_POOL_CREATION_FORM: PoolCreationForm = {
disableUnbalancedLiquidity: false,
hasAcceptedTokenWeightsRisk: false,
hasAcceptedPoolCreationRisk: false,
+ hasAcceptedSimilarPoolsWarning: false,
}
export const INITIAL_RECLAMM_CONFIG: ReClammConfig = {
diff --git a/packages/lib/modules/pool/actions/create/modal/SimilarPoolsModal.tsx b/packages/lib/modules/pool/actions/create/modal/SimilarPoolsModal.tsx
new file mode 100644
index 000000000..aafde6035
--- /dev/null
+++ b/packages/lib/modules/pool/actions/create/modal/SimilarPoolsModal.tsx
@@ -0,0 +1,151 @@
+import { useCheckForSimilarPools } from './useCheckForSimilarPools'
+import { BalAlert } from '@repo/lib/shared/components/alerts/BalAlert'
+import { getChainShortName } from '@repo/lib/config/app.config'
+import { usePoolCreationForm } from '../PoolCreationFormProvider'
+import { PROJECT_CONFIG } from '@repo/lib/config/getProjectConfig'
+import {
+ Modal,
+ ModalContent,
+ ModalBody,
+ VStack,
+ Button,
+ HStack,
+ useDisclosure,
+ Card,
+ Text,
+ Box,
+} from '@chakra-ui/react'
+import { SuccessOverlay } from '@repo/lib/shared/components/modals/SuccessOverlay'
+import { useEffect } from 'react'
+import { TokenIcon } from '@repo/lib/modules/tokens/TokenIcon'
+import { fNum } from '@repo/lib/shared/utils/numbers'
+import { NetworkIcon } from '@repo/lib/shared/components/icons/NetworkIcon'
+import { Link } from '@chakra-ui/react'
+import { ArrowUpRight } from 'react-feather'
+import { getPoolPath } from '@repo/lib/modules/pool/pool.utils'
+import NextLink from 'next/link'
+
+export function SimilarPoolsModal() {
+ const { isOpen, onOpen, onClose } = useDisclosure()
+
+ const { poolCreationForm, resetPoolCreationForm } = usePoolCreationForm()
+ const { network, hasAcceptedSimilarPoolsWarning } = poolCreationForm.watch()
+ const { similarPools } = useCheckForSimilarPools()
+
+ useEffect(() => {
+ if (!hasAcceptedSimilarPoolsWarning && similarPools && similarPools.length > 0) {
+ onOpen()
+ }
+ }, [hasAcceptedSimilarPoolsWarning, similarPools])
+
+ return (
+
+
+
+
+
+
+
+ {similarPools?.slice(0, 3).map(pool => (
+
+
+
+
+
+
+
+
+ {pool.symbol}
+
+
+
+
+ {pool.poolTokens.map(token => (
+
+
+
+
+
+ {token.symbol}
+
+ {token.weight && (
+ {fNum('weight', token.weight)}
+ )}
+
+
+
+ ))}
+
+
+
+ Type: {pool.type.toLowerCase()}
+
+
+ •
+
+
+ TVL: {fNum('fiat', pool.dynamicData.totalLiquidity)}
+
+
+ •
+
+
+ Swap fees: {fNum('feePercent', pool.dynamicData.swapFee)}
+
+
+
+
+ ))}
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/packages/lib/modules/pool/actions/create/modal/useCheckForSimilarPools.ts b/packages/lib/modules/pool/actions/create/modal/useCheckForSimilarPools.ts
new file mode 100644
index 000000000..ebe8fe923
--- /dev/null
+++ b/packages/lib/modules/pool/actions/create/modal/useCheckForSimilarPools.ts
@@ -0,0 +1,46 @@
+import { useQuery } from '@apollo/client'
+import {
+ GetPoolsDocument,
+ GqlPoolOrderBy,
+ GqlPoolOrderDirection,
+} from '@repo/lib/shared/services/api/generated/graphql'
+import { usePoolCreationForm } from '../PoolCreationFormProvider'
+import { getGqlPoolType } from '../helpers'
+
+export function useCheckForSimilarPools() {
+ const { poolCreationForm, isWeightedPool } = usePoolCreationForm()
+ const { network, poolType, poolTokens } = poolCreationForm.watch()
+
+ const { data, loading, error } = useQuery(GetPoolsDocument, {
+ variables: {
+ orderBy: GqlPoolOrderBy.TotalLiquidity,
+ orderDirection: GqlPoolOrderDirection.Desc,
+ where: {
+ chainIn: [network],
+ poolTypeIn: [getGqlPoolType(poolType)],
+ tokensIn: poolTokens.map(({ address }) => address!),
+ protocolVersionIn: [3],
+ },
+ },
+ skip: !network || !poolType || !poolTokens?.every(token => token.address),
+ })
+
+ const similarPools = data?.pools.filter(pool => {
+ const sameNumberOfTokens = pool.poolTokens.length === poolTokens.length
+ const sameWeights =
+ !isWeightedPool ||
+ pool.poolTokens.every(
+ token =>
+ poolTokens.find(poolToken => poolToken.address === token.address)?.weight ===
+ (Number(token.weight) * 100).toString()
+ )
+
+ return sameNumberOfTokens && sameWeights
+ })
+
+ return {
+ similarPools,
+ isLoadingSimilarPools: loading,
+ errorFetchingSimilarPools: error,
+ }
+}
diff --git a/packages/lib/modules/pool/actions/create/steps/details/PoolDetailsStep.tsx b/packages/lib/modules/pool/actions/create/steps/details/PoolDetailsStep.tsx
index 93e96ac94..fee4d11d2 100644
--- a/packages/lib/modules/pool/actions/create/steps/details/PoolDetailsStep.tsx
+++ b/packages/lib/modules/pool/actions/create/steps/details/PoolDetailsStep.tsx
@@ -4,6 +4,7 @@ import { usePoolCreationForm } from '../../PoolCreationFormProvider'
import { PoolDetails } from './PoolDetails'
import { PoolSettings } from './PoolSettings'
import { ReClammConfiguration } from './ReClammConfiguration'
+import { SimilarPoolsModal } from '../../modal/SimilarPoolsModal'
export function PoolDetailsStep() {
const { poolCreationForm, isReClamm } = usePoolCreationForm()
@@ -13,13 +14,16 @@ export function PoolDetailsStep() {
const isDisabled = !isPoolCreationFormValid || !isReClammFormValid
return (
-
-
- {isReClamm && }
-
-
-
-
-
+ <>
+
+
+ {isReClamm && }
+
+
+
+
+
+
+ >
)
}
diff --git a/packages/lib/modules/pool/actions/create/steps/tokens/ChoosePoolTokens.tsx b/packages/lib/modules/pool/actions/create/steps/tokens/ChoosePoolTokens.tsx
index eb6a0a800..1a64afdcb 100644
--- a/packages/lib/modules/pool/actions/create/steps/tokens/ChoosePoolTokens.tsx
+++ b/packages/lib/modules/pool/actions/create/steps/tokens/ChoosePoolTokens.tsx
@@ -77,6 +77,7 @@ export function ChoosePoolTokens() {
})
setSelectedTokenIndex(null)
+ poolCreationForm.setValue('hasAcceptedSimilarPoolsWarning', false)
if (isReClamm) reClammConfigForm.resetToInitial()
}
diff --git a/packages/lib/modules/pool/actions/create/types.ts b/packages/lib/modules/pool/actions/create/types.ts
index 00df3de79..7ef2bd648 100644
--- a/packages/lib/modules/pool/actions/create/types.ts
+++ b/packages/lib/modules/pool/actions/create/types.ts
@@ -49,6 +49,7 @@ export type PoolCreationForm = {
disableUnbalancedLiquidity: boolean
hasAcceptedTokenWeightsRisk: boolean
hasAcceptedPoolCreationRisk: boolean
+ hasAcceptedSimilarPoolsWarning: boolean
}
export type ReClammConfig = {
diff --git a/packages/lib/shared/components/icons/NetworkIcon.tsx b/packages/lib/shared/components/icons/NetworkIcon.tsx
index 850c44ffb..b0541b075 100644
--- a/packages/lib/shared/components/icons/NetworkIcon.tsx
+++ b/packages/lib/shared/components/icons/NetworkIcon.tsx
@@ -9,11 +9,16 @@ type NetworkConfigProps = {
shortName: string
}
-export function NetworkIcon({ chain, size = 12, ...rest }: { chain: GqlChain } & SquareProps) {
+export function NetworkIcon({
+ chain,
+ size = 12,
+ withPadding = true,
+ ...rest
+}: { chain: GqlChain; withPadding?: boolean } & SquareProps) {
const [networkConfig, setNetworkConfig] = useState(undefined)
const { iconPath, shortName } = getNetworkConfig(chain)
- const imageSize = Number(size) * 2 + 8
+ const imageSize = Number(size) * (withPadding ? 2 : 3) + 8
useEffect(() => {
if (shortName && iconPath) {