StakeRewardClaimModalContent.tsx
1 import { ChainId, Stake } from '@aave/contract-helpers'; 2 import { normalize } 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 { 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 { StakeRewardClaimActions } from './StakeRewardClaimActions'; 23 24 export type StakeRewardClaimProps = { 25 stakeAssetName: Stake; 26 icon: string; 27 }; 28 29 export enum ErrorType { 30 NOT_ENOUGH_BALANCE, 31 } 32 33 export const StakeRewardClaimModalContent = ({ stakeAssetName, icon }: StakeRewardClaimProps) => { 34 const { chainId: connectedChainId, readOnlyModeAddress } = useWeb3Context(); 35 const { gasLimit, mainTxState: txState, txError } = useModalContext(); 36 const currentNetworkConfig = useRootStore((store) => store.currentNetworkConfig); 37 const currentChainId = useRootStore((store) => store.currentChainId); 38 const currentMarketData = useRootStore((store) => store.currentMarketData); 39 const [_amount, setAmount] = useState(''); 40 const amountRef = useRef<string>(); 41 42 const { data: stakeUserResult } = useUserStakeUiData(currentMarketData, stakeAssetName); 43 const { data: stakeGeneralResult } = useGeneralStakeUiData(currentMarketData, stakeAssetName); 44 45 const stakeData = stakeGeneralResult?.[0]; 46 const stakeUserData = stakeUserResult?.[0]; 47 48 // hardcoded as all rewards will be in aave token 49 const rewardsSymbol = 'AAVE'; 50 51 const maxAmountToClaim = normalize(stakeUserData?.userIncentivesToClaim || '0', 18); 52 const isMaxSelected = _amount === '-1'; 53 const amount = isMaxSelected ? maxAmountToClaim : _amount; 54 const handleChange = (value: string) => { 55 const maxSelected = value === '-1'; 56 amountRef.current = maxSelected ? maxAmountToClaim : value; 57 setAmount(value); 58 }; 59 60 const amountInUsd = Number(amount) * Number(stakeData?.rewardTokenPriceUSDFormatted); 61 62 // error handler 63 let blockingError: ErrorType | undefined = undefined; 64 if (maxAmountToClaim === '0') { 65 blockingError = ErrorType.NOT_ENOUGH_BALANCE; 66 } 67 68 const handleBlocked = () => { 69 switch (blockingError) { 70 case ErrorType.NOT_ENOUGH_BALANCE: 71 return <Trans>No rewards to claim</Trans>; 72 default: 73 return null; 74 } 75 }; 76 77 // is Network mismatched 78 const stakingChain = 79 currentNetworkConfig.isFork && currentNetworkConfig.underlyingChainId === stakeConfig.chainId 80 ? currentChainId 81 : stakeConfig.chainId; 82 const isWrongNetwork = connectedChainId !== stakingChain; 83 84 const networkConfig = getNetworkConfig(stakingChain); 85 86 if (txError && txError.blocking) { 87 return <TxErrorView txError={txError} />; 88 } 89 if (txState.success) 90 return ( 91 <TxSuccessView 92 action={<Trans>Claimed</Trans>} 93 amount={amountRef.current} 94 symbol={rewardsSymbol} 95 /> 96 ); 97 98 return ( 99 <> 100 <TxModalTitle title="Claim" symbol={rewardsSymbol} /> 101 {isWrongNetwork && !readOnlyModeAddress && ( 102 <ChangeNetworkWarning networkName={networkConfig.name} chainId={stakingChain} /> 103 )} 104 {blockingError !== undefined && ( 105 <Typography variant="helperText" color="red"> 106 {handleBlocked()} 107 </Typography> 108 )} 109 <AssetInput 110 value={amount} 111 onChange={handleChange} 112 usdValue={amountInUsd.toString()} 113 symbol={icon} 114 assets={[ 115 { 116 balance: maxAmountToClaim.toString(), 117 symbol: icon, 118 }, 119 ]} 120 isMaxSelected={isMaxSelected} 121 maxValue={maxAmountToClaim.toString()} 122 balanceText={<Trans>Amount claimable</Trans>} 123 /> 124 <GasStation gasLimit={parseUnits(gasLimit || '0', 'wei')} chainId={ChainId.mainnet} /> 125 126 {txError && <GasEstimationError txError={txError} />} 127 128 <StakeRewardClaimActions 129 sx={{ mt: '48px' }} 130 amountToClaim={amount} 131 isWrongNetwork={isWrongNetwork} 132 symbol={rewardsSymbol} 133 blocked={blockingError !== undefined || Number(amount) === 0} 134 selectedToken={stakeAssetName} 135 /> 136 </> 137 ); 138 };