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

Commit 25330fb

Browse files
authored
Merge pull request #1125 from balancer/feat/update-block-remove-liquidity
feat: update block remove liquidity
2 parents b4839ae + 587f0f2 commit 25330fb

File tree

4 files changed

+72
-7
lines changed

4 files changed

+72
-7
lines changed

lib/modules/pool/actions/remove-liquidity/RemoveLiquidityProvider.tsx

+23-3
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,29 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
104104
const tokenOut =
105105
wethIsEth && wNativeAsset ? (wNativeAsset.address as Address) : singleTokenOutAddress
106106

107+
const isSingleTokenBalanceMoreThat25Percent = useMemo(() => {
108+
if (!pool.userBalance || !isSingleToken) {
109+
return false
110+
}
111+
112+
return bn(pool.userBalance.walletBalance)
113+
.times(bn(humanBptInPercent).div(100))
114+
.gt(bn(pool.dynamicData.totalShares).times(0.25))
115+
}, [singleTokenOutAddress, humanBptInPercent, isSingleToken])
116+
107117
/**
108118
* Queries
109119
*/
120+
121+
const enabled = !urlTxHash && !!tokenOut && !isSingleTokenBalanceMoreThat25Percent
122+
110123
const simulationQuery = useRemoveLiquiditySimulationQuery({
111124
handler,
112125
poolId: pool.id,
113126
chainId,
114127
humanBptIn,
115128
tokenOut,
116-
enabled: !urlTxHash && !!tokenOut,
129+
enabled,
117130
})
118131

119132
const priceImpactQuery = useRemoveLiquidityPriceImpactQuery({
@@ -122,7 +135,7 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
122135
chainId,
123136
humanBptIn,
124137
tokenOut,
125-
enabled: !urlTxHash && !!tokenOut,
138+
enabled,
126139
})
127140

128141
/**
@@ -203,7 +216,13 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
203216
})
204217
)
205218

206-
const totalUSDValue: string = safeSum(Object.values(usdAmountOutMap))
219+
// while the single token balance is more than 25% of the pool, we use the wallet balance usd for the view
220+
const totalUSDValue = isSingleTokenBalanceMoreThat25Percent
221+
? bn(pool.userBalance?.walletBalanceUsd || '0')
222+
.times(bn(humanBptInPercent).div(100))
223+
.toString()
224+
: safeSum(Object.values(usdAmountOutMap))
225+
207226
const totalAmountsOut: string = safeSum(quoteAmountsOut.map(a => a.amount))
208227

209228
const { isDisabled, disabledReason } = isDisabledWithReason(
@@ -260,6 +279,7 @@ export function _useRemoveLiquidity(urlTxHash?: Hash) {
260279
hasQuoteContext,
261280
amountsOut,
262281
removeLiquidityTxSuccess,
282+
isSingleTokenBalanceMoreThat25Percent,
263283
setRemovalType,
264284
setHumanBptInPercent,
265285
setProportionalType,

lib/modules/pool/actions/remove-liquidity/form/RemoveLiquidityForm.tsx

+16-4
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ import { SimulationError } from '@/lib/shared/components/errors/SimulationError'
3535
import { InfoIcon } from '@/lib/shared/components/icons/InfoIcon'
3636
import { SafeAppAlert } from '@/lib/shared/components/alerts/SafeAppAlert'
3737
import { useTokens } from '@/lib/modules/tokens/TokensProvider'
38+
import { TooltipWithTouch } from '@/lib/shared/components/tooltips/TooltipWithTouch'
3839
import { useUserSettings } from '@/lib/modules/user/settings/UserSettingsProvider'
40+
3941
const TABS: ButtonGroupOption[] = [
4042
{
4143
value: 'proportional',
@@ -61,6 +63,8 @@ export function RemoveLiquidityForm() {
6163
simulationQuery,
6264
quoteBptIn,
6365
removeLiquidityTxHash,
66+
isSingleTokenBalanceMoreThat25Percent,
67+
isSingleToken,
6468
setProportionalType,
6569
setSingleTokenType,
6670
setHumanBptInPercent,
@@ -113,6 +117,8 @@ export function RemoveLiquidityForm() {
113117
}
114118
}, [removeLiquidityTxHash])
115119

120+
const isWarning = isSingleToken && isSingleTokenBalanceMoreThat25Percent
121+
116122
return (
117123
<TokenBalancesProvider extTokens={validTokens}>
118124
<Box h="full" w="full" maxW="lg" mx="auto" pb="2xl">
@@ -139,17 +145,23 @@ export function RemoveLiquidityForm() {
139145
</Tooltip>
140146
</HStack>
141147
)}
142-
<VStack w="full" spacing="md">
148+
<VStack w="full" spacing="md" align="start">
143149
<InputWithSlider
144150
value={totalUSDValue}
145151
onPercentChanged={setHumanBptInPercent}
146152
isNumberInputDisabled
153+
isWarning={isWarning}
147154
>
148155
<Text fontSize="sm">Amount</Text>
149156
<Text fontSize="sm" variant="secondary">
150157
{fNum('percentage', humanBptInPercent / 100)}
151158
</Text>
152159
</InputWithSlider>
160+
{isWarning && (
161+
<Text fontSize="xs" color="font.warning">
162+
You can only remove up to 25% of a single asset from the pool in one transaction
163+
</Text>
164+
)}
153165
{activeTab === TABS[0] && (
154166
<RemoveLiquidityProportional tokens={tokens} poolType={pool.type} />
155167
)}
@@ -188,19 +200,19 @@ export function RemoveLiquidityForm() {
188200
)}
189201
</VStack>
190202
<SimulationError simulationQuery={simulationQuery} />
191-
<Tooltip label={isDisabled ? disabledReason : ''}>
203+
<TooltipWithTouch label={isDisabled ? disabledReason : ''}>
192204
<Button
193205
ref={nextBtn}
194206
variant="secondary"
195207
w="full"
196208
size="lg"
197-
isDisabled={isDisabled}
209+
isDisabled={isDisabled || isWarning}
198210
isLoading={simulationQuery.isLoading || priceImpactQuery.isLoading}
199211
onClick={() => !isDisabled && previewModalDisclosure.onOpen()}
200212
>
201213
Next
202214
</Button>
203-
</Tooltip>
215+
</TooltipWithTouch>
204216
</VStack>
205217
</Card>
206218
<RemoveLiquidityModal

lib/shared/components/inputs/InputWithSlider/InputWithSlider.tsx

+14
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@ import {
1515
SliderTrack,
1616
VStack,
1717
forwardRef,
18+
useTheme as useChakraTheme,
1819
} from '@chakra-ui/react'
1920
import { useState } from 'react'
21+
import { useTheme as useNextTheme } from 'next-themes'
2022

2123
type Props = {
2224
value?: string
2325
boxProps?: BoxProps
2426
onPercentChanged: (percent: number) => void
2527
isNumberInputDisabled?: boolean
28+
isWarning?: boolean
2629
}
2730

2831
export const InputWithSlider = forwardRef(
@@ -33,12 +36,15 @@ export const InputWithSlider = forwardRef(
3336
onPercentChanged,
3437
children,
3538
isNumberInputDisabled,
39+
isWarning,
3640
...numberInputProps
3741
}: NumberInputProps & Props,
3842
ref
3943
) => {
4044
const [sliderPercent, setSliderPercent] = useState<number>(100)
4145
const { toCurrency } = useCurrency()
46+
const theme = useChakraTheme()
47+
const { theme: nextTheme } = useNextTheme()
4248

4349
function handleSliderChange(percent: number) {
4450
setSliderPercent(percent)
@@ -56,6 +62,13 @@ export const InputWithSlider = forwardRef(
5662
// setSliderPercent(newPercent)
5763
}
5864

65+
const boxShadowColor =
66+
nextTheme === 'dark'
67+
? theme.semanticTokens.colors.font.warning._dark
68+
: theme.semanticTokens.colors.font.warning.default
69+
70+
const boxShadow = isWarning ? `0 0 0 1px ${boxShadowColor}` : undefined
71+
5972
return (
6073
<VStack w="full" spacing="xs">
6174
{children && (
@@ -72,6 +85,7 @@ export const InputWithSlider = forwardRef(
7285
border="white"
7386
w="full"
7487
ref={ref}
88+
boxShadow={boxShadow}
7589
{...boxProps}
7690
>
7791
<HStack align="start" spacing="md">
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Tooltip, Box, TooltipProps } from '@chakra-ui/react'
2+
import { useState } from 'react'
3+
4+
export const TooltipWithTouch = ({ children, ...rest }: TooltipProps) => {
5+
const [isLabelOpen, setIsLabelOpen] = useState(false)
6+
7+
return (
8+
<Tooltip isOpen={isLabelOpen} {...rest}>
9+
<Box
10+
w="full"
11+
onMouseEnter={() => setIsLabelOpen(true)}
12+
onMouseLeave={() => setIsLabelOpen(false)}
13+
onClick={() => setIsLabelOpen(true)}
14+
>
15+
{children}
16+
</Box>
17+
</Tooltip>
18+
)
19+
}

0 commit comments

Comments
 (0)