Skip to content
This repository has been archived by the owner on Oct 15, 2024. It is now read-only.

feat: update block remove liquidity #1125

Merged
merged 9 commits into from
Oct 3, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -104,16 +104,29 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
const tokenOut =
wethIsEth && wNativeAsset ? (wNativeAsset.address as Address) : singleTokenOutAddress

const isSingleTokenBalanceMoreThat25Percent = useMemo(() => {
if (!pool.userBalance || !isSingleToken) {
return false
}

return bn(pool.userBalance.walletBalance)
.times(bn(humanBptInPercent).div(100))
.gt(bn(pool.dynamicData.totalShares).times(0.25))
}, [singleTokenOutAddress, humanBptInPercent, isSingleToken])

/**
* Queries
*/

const enabled = !urlTxHash && !!tokenOut && !isSingleTokenBalanceMoreThat25Percent

const simulationQuery = useRemoveLiquiditySimulationQuery({
handler,
poolId: pool.id,
chainId,
humanBptIn,
tokenOut,
enabled: !urlTxHash && !!tokenOut,
enabled,
})

const priceImpactQuery = useRemoveLiquidityPriceImpactQuery({
Expand All @@ -122,7 +135,7 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
chainId,
humanBptIn,
tokenOut,
enabled: !urlTxHash && !!tokenOut,
enabled,
})

/**
Expand Down Expand Up @@ -203,7 +216,13 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
})
)

const totalUSDValue: string = safeSum(Object.values(usdAmountOutMap))
// while the single token balance is more than 25% of the pool, we use the wallet balance usd for the view
const totalUSDValue = isSingleTokenBalanceMoreThat25Percent
? bn(pool.userBalance?.walletBalanceUsd || '0')
.times(bn(humanBptInPercent).div(100))
.toString()
: safeSum(Object.values(usdAmountOutMap))

const totalAmountsOut: string = safeSum(quoteAmountsOut.map(a => a.amount))

const { isDisabled, disabledReason } = isDisabledWithReason(
Expand Down Expand Up @@ -260,6 +279,7 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
hasQuoteContext,
amountsOut,
removeLiquidityTxSuccess,
isSingleTokenBalanceMoreThat25Percent,
setRemovalType,
setHumanBptInPercent,
setProportionalType,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ import { SimulationError } from '@/lib/shared/components/errors/SimulationError'
import { InfoIcon } from '@/lib/shared/components/icons/InfoIcon'
import { SafeAppAlert } from '@/lib/shared/components/alerts/SafeAppAlert'
import { useTokens } from '@/lib/modules/tokens/TokensProvider'
import { TooltipWithTouch } from '@/lib/shared/components/tooltips/TooltipWithTouch'
import { useUserSettings } from '@/lib/modules/user/settings/UserSettingsProvider'

const TABS: ButtonGroupOption[] = [
{
value: 'proportional',
Expand All @@ -61,6 +63,8 @@ export function RemoveLiquidityForm() {
simulationQuery,
quoteBptIn,
removeLiquidityTxHash,
isSingleTokenBalanceMoreThat25Percent,
isSingleToken,
setProportionalType,
setSingleTokenType,
setHumanBptInPercent,
Expand Down Expand Up @@ -113,6 +117,8 @@ export function RemoveLiquidityForm() {
}
}, [removeLiquidityTxHash])

const isWarning = isSingleToken && isSingleTokenBalanceMoreThat25Percent

return (
<TokenBalancesProvider extTokens={validTokens}>
<Box h="full" w="full" maxW="lg" mx="auto" pb="2xl">
Expand All @@ -139,17 +145,23 @@ export function RemoveLiquidityForm() {
</Tooltip>
</HStack>
)}
<VStack w="full" spacing="md">
<VStack w="full" spacing="md" align="start">
<InputWithSlider
value={totalUSDValue}
onPercentChanged={setHumanBptInPercent}
isNumberInputDisabled
isWarning={isWarning}
>
<Text fontSize="sm">Amount</Text>
<Text fontSize="sm" variant="secondary">
{fNum('percentage', humanBptInPercent / 100)}
</Text>
</InputWithSlider>
{isWarning && (
<Text fontSize="xs" color="font.warning">
You can only remove up to 25% of a single asset from the pool in one transaction
</Text>
)}
{activeTab === TABS[0] && (
<RemoveLiquidityProportional tokens={tokens} poolType={pool.type} />
)}
Expand Down Expand Up @@ -188,19 +200,19 @@ export function RemoveLiquidityForm() {
)}
</VStack>
<SimulationError simulationQuery={simulationQuery} />
<Tooltip label={isDisabled ? disabledReason : ''}>
<TooltipWithTouch label={isDisabled ? disabledReason : ''}>
<Button
ref={nextBtn}
variant="secondary"
w="full"
size="lg"
isDisabled={isDisabled}
isDisabled={isDisabled || isWarning}
isLoading={simulationQuery.isLoading || priceImpactQuery.isLoading}
onClick={() => !isDisabled && previewModalDisclosure.onOpen()}
>
Next
</Button>
</Tooltip>
</TooltipWithTouch>
</VStack>
</Card>
<RemoveLiquidityModal
Expand Down
14 changes: 14 additions & 0 deletions lib/shared/components/inputs/InputWithSlider/InputWithSlider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@ import {
SliderTrack,
VStack,
forwardRef,
useTheme as useChakraTheme,
} from '@chakra-ui/react'
import { useState } from 'react'
import { useTheme as useNextTheme } from 'next-themes'

type Props = {
value?: string
boxProps?: BoxProps
onPercentChanged: (percent: number) => void
isNumberInputDisabled?: boolean
isWarning?: boolean
}

export const InputWithSlider = forwardRef(
Expand All @@ -33,12 +36,15 @@ export const InputWithSlider = forwardRef(
onPercentChanged,
children,
isNumberInputDisabled,
isWarning,
...numberInputProps
}: NumberInputProps & Props,
ref
) => {
const [sliderPercent, setSliderPercent] = useState<number>(100)
const { toCurrency } = useCurrency()
const theme = useChakraTheme()
const { theme: nextTheme } = useNextTheme()

function handleSliderChange(percent: number) {
setSliderPercent(percent)
Expand All @@ -56,6 +62,13 @@ export const InputWithSlider = forwardRef(
// setSliderPercent(newPercent)
}

const boxShadowColor =
nextTheme === 'dark'
? theme.semanticTokens.colors.font.warning._dark
: theme.semanticTokens.colors.font.warning.default

const boxShadow = isWarning ? `0 0 0 1px ${boxShadowColor}` : undefined

return (
<VStack w="full" spacing="xs">
{children && (
Expand All @@ -72,6 +85,7 @@ export const InputWithSlider = forwardRef(
border="white"
w="full"
ref={ref}
boxShadow={boxShadow}
{...boxProps}
>
<HStack align="start" spacing="md">
Expand Down
19 changes: 19 additions & 0 deletions lib/shared/components/tooltips/TooltipWithTouch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Tooltip, Box, TooltipProps } from '@chakra-ui/react'
import { useState } from 'react'

export const TooltipWithTouch = ({ children, ...rest }: TooltipProps) => {
const [isLabelOpen, setIsLabelOpen] = useState(false)

return (
<Tooltip isOpen={isLabelOpen} {...rest}>
<Box
w="full"
onMouseEnter={() => setIsLabelOpen(true)}
onMouseLeave={() => setIsLabelOpen(false)}
onClick={() => setIsLabelOpen(true)}
>
{children}
</Box>
</Tooltip>
)
}
Loading