/ src / components / transactions / StakingMigrate / StakingMigrateModalContent.tsx
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  };