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 };