/ src / components / transactions / UnStake / UnStakeModalContent.tsx
UnStakeModalContent.tsx
  1  import { ChainId, Stake } from '@aave/contract-helpers';
  2  import { normalize, valueToBigNumber } from '@aave/math-utils';
  3  import { Trans } from '@lingui/macro';
  4  import { Typography } from '@mui/material';
  5  import { parseUnits } from 'ethers/lib/utils';
  6  import React, { useRef, useState } from 'react';
  7  import { useGeneralStakeUiData } from 'src/hooks/stake/useGeneralStakeUiData';
  8  import { useUserStakeUiData } from 'src/hooks/stake/useUserStakeUiData';
  9  import { useModalContext } from 'src/hooks/useModal';
 10  import { useWeb3Context } from 'src/libs/hooks/useWeb3Context';
 11  import { useRootStore } from 'src/store/root';
 12  import { stakeAssetNameFormatted, stakeConfig } from 'src/ui-config/stakeConfig';
 13  import { getNetworkConfig } from 'src/utils/marketsAndNetworksConfig';
 14  
 15  import { AssetInput } from '../AssetInput';
 16  import { TxErrorView } from '../FlowCommons/Error';
 17  import { GasEstimationError } from '../FlowCommons/GasEstimationError';
 18  import { TxSuccessView } from '../FlowCommons/Success';
 19  import { TxModalTitle } from '../FlowCommons/TxModalTitle';
 20  import { GasStation } from '../GasStation/GasStation';
 21  import { ChangeNetworkWarning } from '../Warnings/ChangeNetworkWarning';
 22  import { UnStakeActions } from './UnStakeActions';
 23  
 24  export type UnStakeProps = {
 25    stakeAssetName: Stake;
 26    icon: string;
 27  };
 28  
 29  export enum ErrorType {
 30    NOT_ENOUGH_BALANCE,
 31  }
 32  
 33  export const UnStakeModalContent = ({ stakeAssetName, icon }: UnStakeProps) => {
 34    const { chainId: connectedChainId, readOnlyModeAddress } = useWeb3Context();
 35    const { gasLimit, mainTxState: txState, txError } = useModalContext();
 36    const currentMarketData = useRootStore((store) => store.currentMarketData);
 37    const currentNetworkConfig = useRootStore((store) => store.currentNetworkConfig);
 38    const currentChainId = useRootStore((store) => store.currentChainId);
 39  
 40    const { data: stakeUserResult } = useUserStakeUiData(currentMarketData, stakeAssetName);
 41    const { data: stakeGeneralResult } = useGeneralStakeUiData(currentMarketData, stakeAssetName);
 42  
 43    const stakeData = stakeGeneralResult?.[0];
 44    const stakeUserData = stakeUserResult?.[0];
 45  
 46    // states
 47    const [_amount, setAmount] = useState('');
 48    const amountRef = useRef<string>();
 49  
 50    let amountToUnstake = stakeUserData?.userCooldownAmount;
 51    if (stakeData?.inPostSlashingPeriod) {
 52      amountToUnstake = stakeUserData?.stakeTokenUserBalance;
 53    }
 54  
 55    const balance = normalize(amountToUnstake || '0', 18);
 56  
 57    const isMaxSelected = _amount === '-1';
 58    const amount = isMaxSelected ? balance : _amount;
 59  
 60    const handleChange = (value: string) => {
 61      const maxSelected = value === '-1';
 62      amountRef.current = maxSelected ? balance : value;
 63      setAmount(value);
 64    };
 65  
 66    // staking token usd value
 67    const amountInUsd = Number(amount) * Number(stakeData?.stakeTokenPriceUSDFormatted);
 68  
 69    // error handler
 70    let blockingError: ErrorType | undefined = undefined;
 71    if (valueToBigNumber(amount).gt(balance)) {
 72      blockingError = ErrorType.NOT_ENOUGH_BALANCE;
 73    }
 74  
 75    const handleBlocked = () => {
 76      switch (blockingError) {
 77        case ErrorType.NOT_ENOUGH_BALANCE:
 78          return <Trans>Not enough staked balance</Trans>;
 79        default:
 80          return null;
 81      }
 82    };
 83  
 84    const nameFormatted = stakeAssetNameFormatted(stakeAssetName);
 85  
 86    // is Network mismatched
 87    const stakingChain =
 88      currentNetworkConfig.isFork && currentNetworkConfig.underlyingChainId === stakeConfig.chainId
 89        ? currentChainId
 90        : stakeConfig.chainId;
 91    const isWrongNetwork = connectedChainId !== stakingChain;
 92  
 93    const networkConfig = getNetworkConfig(stakingChain);
 94  
 95    if (txError && txError.blocking) {
 96      return <TxErrorView txError={txError} />;
 97    }
 98    if (txState.success)
 99      return (
100        <TxSuccessView
101          action={<Trans>Unstaked</Trans>}
102          amount={amountRef.current}
103          symbol={nameFormatted}
104        />
105      );
106  
107    console.log(icon);
108    return (
109      <>
110        <TxModalTitle title="Unstake" symbol={nameFormatted} />
111        {isWrongNetwork && !readOnlyModeAddress && (
112          <ChangeNetworkWarning networkName={networkConfig.name} chainId={stakingChain} />
113        )}
114        <AssetInput
115          value={amount}
116          onChange={handleChange}
117          usdValue={amountInUsd.toString()}
118          symbol={nameFormatted}
119          assets={[
120            {
121              balance: balance,
122              symbol: icon,
123            },
124          ]}
125          isMaxSelected={isMaxSelected}
126          maxValue={balance}
127          balanceText={<Trans>Staking balance</Trans>}
128        />
129        {blockingError !== undefined && (
130          <Typography variant="helperText" color="red">
131            {handleBlocked()}
132          </Typography>
133        )}
134        <GasStation gasLimit={parseUnits(gasLimit || '0', 'wei')} chainId={ChainId.mainnet} />
135  
136        {txError && <GasEstimationError txError={txError} />}
137  
138        <UnStakeActions
139          sx={{ mt: '48px' }}
140          amountToUnStake={amount}
141          isWrongNetwork={isWrongNetwork}
142          symbol={nameFormatted}
143          blocked={blockingError !== undefined}
144          selectedToken={stakeAssetName}
145        />
146      </>
147    );
148  };