StakingMigrateModalContent.tsx
1 import { Stake, valueToWei } from '@aave/contract-helpers'; 2 import { normalize } from '@aave/math-utils'; 3 import { Trans } from '@lingui/macro'; 4 import { Box } from '@mui/material'; 5 import { BigNumber } from 'ethers'; 6 import { formatEther } from 'ethers/lib/utils'; 7 import { ReactNode, useRef, useState } from 'react'; 8 import { FormattedNumber } from 'src/components/primitives/FormattedNumber'; 9 import { Row } from 'src/components/primitives/Row'; 10 import { useGeneralStakeUiData } from 'src/hooks/stake/useGeneralStakeUiData'; 11 import { useUserStakeUiData } from 'src/hooks/stake/useUserStakeUiData'; 12 import { useModalContext } from 'src/hooks/useModal'; 13 import { useRootStore } from 'src/store/root'; 14 import { stakeAssetNameFormatted } from 'src/ui-config/stakeConfig'; 15 16 import { AssetInput } from '../AssetInput'; 17 import { TxSuccessView } from '../FlowCommons/Success'; 18 import { TxModalDetails } from '../FlowCommons/TxModalDetails'; 19 import { TxModalTitle } from '../FlowCommons/TxModalTitle'; 20 import { StakingMigrateActions } from './StakingMigrateActions'; 21 22 export const StakingMigrateModalContent = () => { 23 const { gasLimit, mainTxState } = useModalContext(); 24 const currentMarketData = useRootStore((store) => store.currentMarketData); 25 const { data: stkBptUserData } = useUserStakeUiData(currentMarketData, Stake.bpt); 26 27 const { data: stkBptData } = useGeneralStakeUiData(currentMarketData, Stake.bpt); 28 const { data: stkBptV2Data } = useGeneralStakeUiData(currentMarketData, Stake.bptv2); 29 30 const stakeData = stkBptData?.[0]; 31 const stakeUserData = stkBptUserData?.[0]; 32 const stakeBptV2Data = stkBptV2Data?.[0]; 33 34 const [_amount, setAmount] = useState(''); 35 const amountRef = useRef<string>(); 36 37 const maxAmountToMigrate = normalize(stakeUserData?.stakeTokenUserBalance || '0', 18); 38 const isMaxSelected = _amount === '-1'; 39 const amount = isMaxSelected ? maxAmountToMigrate : _amount; 40 const handleChange = (value: string) => { 41 const maxSelected = value === '-1'; 42 amountRef.current = maxSelected ? maxAmountToMigrate : value; 43 setAmount(value); 44 }; 45 46 // staking token usd value 47 const amountInUsd = Number(amount) * Number(stakeData?.stakeTokenPriceUSDFormatted); 48 49 if (mainTxState.success) 50 return ( 51 <TxSuccessView 52 action={<Trans>Migrated</Trans>} 53 amount={amountRef.current} 54 symbol={'stkABPT'} 55 /> 56 ); 57 58 const expectedBptOut = BigNumber.from(valueToWei(amount || '0', 18)) 59 .mul(BigNumber.from(stakeData?.stakeTokenPriceUSD || 0)) 60 .div(BigNumber.from(stakeBptV2Data?.stakeTokenPriceUSD || 0)); 61 62 const minBptOutWithSlippage = expectedBptOut.mul(9999).div(10000).toString(); 63 64 const minOutFormatted = formatEther(minBptOutWithSlippage); 65 const minOutUSD = Number(minOutFormatted) * Number(stakeBptV2Data?.stakeTokenPriceUSDFormatted); 66 67 const nameFormatted = stakeAssetNameFormatted(Stake.bpt); 68 69 return ( 70 <> 71 <TxModalTitle title={<Trans>Migrate to stkABPT v2</Trans>} /> 72 <AssetInput 73 value={amount} 74 onChange={handleChange} 75 usdValue={amountInUsd.toString()} 76 symbol={nameFormatted} 77 assets={[ 78 { 79 balance: maxAmountToMigrate.toString(), 80 symbol: 'stkBPT', 81 }, 82 ]} 83 isMaxSelected={isMaxSelected} 84 maxValue={maxAmountToMigrate.toString()} 85 balanceText={<Trans>Wallet balance</Trans>} 86 /> 87 <TxModalDetails gasLimit={gasLimit}> 88 <TxDetailsRow 89 caption={<Trans>Amount to migrate</Trans>} 90 value={amount} 91 valueUSD={amountInUsd.toString()} 92 /> 93 <TxDetailsRow 94 caption={<Trans>Minimum amount received</Trans>} 95 value={formatEther(minBptOutWithSlippage)} 96 valueUSD={minOutUSD.toString()} 97 /> 98 </TxModalDetails> 99 <StakingMigrateActions amountToMigrate={amount} minOutWithSlippage={minBptOutWithSlippage} /> 100 </> 101 ); 102 }; 103 104 type TxDetailsRowProps = { 105 caption: ReactNode; 106 value: string; 107 valueUSD: string; 108 }; 109 110 const TxDetailsRow = ({ caption, value, valueUSD }: TxDetailsRowProps) => { 111 return ( 112 <Row caption={caption} captionVariant="description" mb={4}> 113 <Box sx={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-end' }}> 114 <Box sx={{ display: 'flex', alignItems: 'center' }}> 115 <FormattedNumber value={value} variant="secondary14" compact /> 116 </Box> 117 <FormattedNumber 118 value={valueUSD} 119 variant="helperText" 120 compact 121 symbol="USD" 122 symbolsColor="text.secondary" 123 color="text.secondary" 124 /> 125 </Box> 126 </Row> 127 ); 128 };