diff --git a/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx b/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx index 29cc7053..cbb41e24 100644 --- a/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx +++ b/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/stake/page.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/exhaustive-deps */ 'use client' import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' diff --git a/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/swap/[[...txHash]]/page.tsx b/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/swap/[[...txHash]]/page.tsx new file mode 100644 index 00000000..40530854 --- /dev/null +++ b/apps/frontend-v3/app/(app)/pools/[chain]/[variant]/[id]/swap/[[...txHash]]/page.tsx @@ -0,0 +1,44 @@ +'use client' + +import { PoolActionsLayout } from '@repo/lib/modules/pool/actions/PoolActionsLayout' +import { getPoolTokens } from '@repo/lib/modules/pool/pool.helpers' +import { usePoolRedirect } from '@repo/lib/modules/pool/pool.hooks' +import { chainToSlugMap } from '@repo/lib/modules/pool/pool.utils' +import { usePool } from '@repo/lib/modules/pool/PoolProvider' +import { SwapForm } from '@repo/lib/modules/swap/SwapForm' +import SwapLayout from '@repo/lib/modules/swap/SwapLayout' +import { PathParams } from '@repo/lib/modules/swap/SwapProvider' +import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' +import { Hash } from 'viem' + +type Props = { + params: { txHash?: string[] } +} +// Page for swapping from a pool page +export default function PoolSwapPage({ params: { txHash } }: Props) { + const { getToken } = useTokens() + const { pool, isLoading } = usePool() + const { redirectToPoolPage } = usePoolRedirect(pool) + + const poolTokens = getPoolTokens(pool, getToken) + + const maybeTxHash = (txHash?.[0] as Hash) || undefined + + const pathParams: PathParams = { + chain: chainToSlugMap[pool.chain], + tokenIn: poolTokens[0].address, + tokenOut: poolTokens[1].address, + poolTokens, + urlTxHash: maybeTxHash, + } + + return ( + + {isLoading ? null : ( + + + + )} + + ) +} diff --git a/apps/frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx b/apps/frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx index 7f4cf9ff..fe321954 100644 --- a/apps/frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx +++ b/apps/frontend-v3/app/(app)/swap/[[...slug]]/layout.tsx @@ -1,44 +1,20 @@ 'use client' -import { ChainSlug, slugToChainMap } from '@repo/lib/modules/pool/pool.utils' -import { SwapProvider } from '@repo/lib/modules/swap/SwapProvider' -import { TokenBalancesProvider } from '@repo/lib/modules/tokens/TokenBalancesProvider' -import { TokenInputsValidationProvider } from '@repo/lib/modules/tokens/TokenInputsValidationProvider' -import { useTokens } from '@repo/lib/modules/tokens/TokensProvider' -import { TransactionStateProvider } from '@repo/lib/modules/transactions/transaction-steps/TransactionStateProvider' -import { GqlChain } from '@repo/lib/shared/services/api/generated/graphql' import { PropsWithChildren } from 'react' -import { PriceImpactProvider } from '@repo/lib/modules/price-impact/PriceImpactProvider' -import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' import { getSwapPathParams } from '@repo/lib/modules/swap/getSwapPathParams' -import { RelayerSignatureProvider } from '@repo/lib/modules/relayer/RelayerSignatureProvider' +import SwapLayout from '../../../../../../packages/lib/modules/swap/SwapLayout' +import { DefaultPageContainer } from '@repo/lib/shared/components/containers/DefaultPageContainer' type Props = PropsWithChildren<{ params: { slug?: string[] } }> -export default function SwapLayout({ params: { slug }, children }: Props) { +export default function Layout({ params: { slug }, children }: Props) { const pathParams = getSwapPathParams(slug) - const { getTokensByChain } = useTokens() - const initChain = pathParams.chain - ? slugToChainMap[pathParams.chain as ChainSlug] - : GqlChain.Mainnet - const initTokens = getTokensByChain(initChain) - return ( - - - - - - {children} - - - - - + {children} ) } diff --git a/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolAdvancedOptions.tsx b/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolAdvancedOptions.tsx new file mode 100644 index 00000000..adb92fd3 --- /dev/null +++ b/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolAdvancedOptions.tsx @@ -0,0 +1,70 @@ +'use client' + +import { + Box, + Button, + HStack, + Link, + Popover, + PopoverArrow, + PopoverBody, + PopoverCloseButton, + PopoverContent, + PopoverTrigger, + VStack, +} from '@chakra-ui/react' +import { SwapIcon } from '@repo/lib/shared/components/icons/SwapIcon' +import { staggeredFadeInUp } from '@repo/lib/shared/utils/animations' +import { AnimatePresence, motion } from 'framer-motion' +import NextLink from 'next/link' +import { usePathname } from 'next/navigation' +import { useState } from 'react' +import { MoreVertical } from 'react-feather' + +export function PoolAdvancedOptions() { + const [isPopoverOpen, setIsPopoverOpen] = useState(false) + const pathname = usePathname() + + return ( + setIsPopoverOpen(true)} + onClose={() => setIsPopoverOpen(false)} + placement="bottom-end" + > + + + + + + + + + + {isPopoverOpen && ( + + + + + Swap tokens directly via this pool + + + + )} + + + + + + ) +} diff --git a/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolHeader.tsx b/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolHeader.tsx index 37c7571a..18369650 100644 --- a/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolHeader.tsx +++ b/packages/lib/modules/pool/PoolDetail/PoolHeader/PoolHeader.tsx @@ -1,4 +1,4 @@ -import { Stack, Button, VStack, useDisclosure } from '@chakra-ui/react' +import { Stack, Button, VStack, useDisclosure, HStack } from '@chakra-ui/react' import { usePathname, useRouter } from 'next/navigation' import PoolMetaBadges from './PoolMetaBadges' @@ -13,6 +13,7 @@ import { } from '@repo/lib/shared/components/modals/PartnerRedirectModal' import { useState } from 'react' import { getXavePoolLink } from '../../pool.utils' +import { PoolAdvancedOptions } from './PoolAdvancedOptions' export function PoolHeader() { const pathname = usePathname() @@ -55,14 +56,18 @@ export function PoolHeader() { - + + + + + + + } + /> + + + + {pool.name} (swap route) + + + + ) +} diff --git a/packages/lib/modules/swap/SwapForm.tsx b/packages/lib/modules/swap/SwapForm.tsx index 4a0d526f..bb4372fd 100644 --- a/packages/lib/modules/swap/SwapForm.tsx +++ b/packages/lib/modules/swap/SwapForm.tsx @@ -38,8 +38,14 @@ import { useUserAccount } from '../web3/UserAccountProvider' import { ConnectWallet } from '../web3/ConnectWallet' import { SafeAppAlert } from '@repo/lib/shared/components/alerts/SafeAppAlert' import { useTokens } from '../tokens/TokensProvider' +import { useIsPoolSwap } from './useIsPoolSwap' +import { CompactTokenSelectModal } from '../tokens/TokenSelectModal/TokenSelectList/CompactTokenSelectModal' +import { PoolSwapCard } from './PoolSwapCard' -export function SwapForm() { +type Props = { + redirectToPoolPage?: () => void // Only used for pool swaps +} +export function SwapForm({ redirectToPoolPage }: Props) { const { tokenIn, tokenOut, @@ -72,6 +78,7 @@ export function SwapForm() { const isMounted = useIsMounted() const { isConnected } = useUserAccount() const { startTokenPricePolling } = useTokens() + const isPoolSwap = useIsPoolSwap() const isLoadingSwaps = simulationQuery.isLoading const isLoading = isLoadingSwaps || !isMounted @@ -107,8 +114,9 @@ export function SwapForm() { if (swapTxHash) { resetSwapAmounts() - replaceUrlPath() transactionSteps.resetTransactionSteps() + if (isPoolSwap) return redirectToPoolPage?.() + replaceUrlPath() } } @@ -124,7 +132,7 @@ export function SwapForm() { > - {capitalize(swapAction)} + {isPoolSwap ? 'Single pool swap' : capitalize(swapAction)}