diff --git a/src/components/Forms/TokenAmountForm.tsx b/src/components/Forms/TokenAmountForm.tsx index 090aaee32..9ac614054 100644 --- a/src/components/Forms/TokenAmountForm.tsx +++ b/src/components/Forms/TokenAmountForm.tsx @@ -5,7 +5,11 @@ import ThresholdCircleBrand from "../../static/icons/ThresholdCircleBrand" import { FormikTokenBalanceInput } from "./FormikTokenBalanceInput" import SubmitTxButton from "../SubmitTxButton" import { Form } from "./Form" -import { getErrorsObj, validateAmountInRange } from "../../utils/forms" +import { + DEFAULT_MIN_VALUE, + getErrorsObj, + validateAmountInRange, +} from "../../utils/forms" import { formatTokenAmount } from "../../utils/formatAmount" export type FormValues = { @@ -25,6 +29,8 @@ type TokenAmountFormProps = { shouldDisplayMaxAmountInLabel?: boolean token?: { decimals: number; symbol: string } innerRef?: Ref> + placeholder?: string + minTokenAmount?: string | number } const TokenAmountFormBase: FC< @@ -39,6 +45,7 @@ const TokenAmountFormBase: FC< isDisabled = false, shouldValidateForm = true, shouldDisplayMaxAmountInLabel = false, + placeholder, ...formikProps }) => { return ( @@ -60,7 +67,7 @@ const TokenAmountFormBase: FC< label ) } - placeholder={`${token.symbol} amount`} + placeholder={placeholder || `${token.symbol} amount`} icon={icon} mb={2} max={maxTokenAmount} @@ -88,7 +95,8 @@ export const TokenAmountForm = withFormik({ errors.tokenAmount = validateAmountInRange( values.tokenAmount, - props.maxTokenAmount.toString() + props.maxTokenAmount.toString(), + props.minTokenAmount ? props.minTokenAmount.toString() : DEFAULT_MIN_VALUE ) return getErrorsObj(errors) }, @@ -100,4 +108,5 @@ export const TokenAmountForm = withFormik({ TokenAmountForm.defaultProps = { shouldValidateForm: true, + minTokenAmount: DEFAULT_MIN_VALUE, } diff --git a/src/hooks/useMinStakeAmount.ts b/src/hooks/useMinStakeAmount.ts new file mode 100644 index 000000000..09278ce8d --- /dev/null +++ b/src/hooks/useMinStakeAmount.ts @@ -0,0 +1,25 @@ +import { useEffect } from "react" +import { useDispatch } from "react-redux" +import { setMinStake } from "../store/staking" +import { useTStakingContract } from "../web3/hooks" +import { useStakingState } from "./useStakingState" + +export const useMinStakeAmount = () => { + const tStakingContract = useTStakingContract() + const { minStakeAmount } = useStakingState() + const dispatch = useDispatch() + + useEffect(() => { + const fetchMinStakeAmount = async () => { + try { + const minStakeAmount = await tStakingContract?.minTStakeAmount() + dispatch(setMinStake({ amount: minStakeAmount.toString() })) + } catch (error) { + console.error("Could not fetch the min stake amount: ", error) + } + } + if (minStakeAmount === "0" && tStakingContract) fetchMinStakeAmount() + }, [tStakingContract, dispatch, minStakeAmount]) + + return minStakeAmount +} diff --git a/src/pages/Staking/StakedPortfolioCard.tsx b/src/pages/Staking/StakedPortfolioCard.tsx index cd416bc1d..bb548dfc2 100644 --- a/src/pages/Staking/StakedPortfolioCard.tsx +++ b/src/pages/Staking/StakedPortfolioCard.tsx @@ -12,10 +12,12 @@ import { useModal } from "../../hooks/useModal" import { useTokenBalance } from "../../hooks/useTokenBalance" import { ModalType, Token } from "../../enums" import { formatTokenAmount } from "../../utils/formatAmount" +import { useMinStakeAmount } from "../../hooks/useMinStakeAmount" const StakedPortfolioCard: FC> = (props) => { const { openModal } = useModal() const tBalance = useTokenBalance(Token.T) + const minStakeAmount = useMinStakeAmount() const openStakingModal = async (stakeAmount: string) => { openModal(ModalType.StakingChecklist, { stakeAmount }) @@ -47,6 +49,12 @@ const StakedPortfolioCard: FC> = (props) => { label="Stake Amount" submitButtonText="Stake" maxTokenAmount={tBalance} + placeholder={`Minimum stake ${ + minStakeAmount === "0" + ? "loading..." + : `${formatTokenAmount(minStakeAmount)} T` + }`} + minTokenAmount={minStakeAmount} /> diff --git a/src/store/staking/stakingSlice.ts b/src/store/staking/stakingSlice.ts index cca8136f5..57cd1fce7 100644 --- a/src/store/staking/stakingSlice.ts +++ b/src/store/staking/stakingSlice.ts @@ -24,6 +24,7 @@ interface StakingState { stakedBalance: BigNumberish totalRewardsBalance: string totalBonusBalance: string + minStakeAmount: string } const calculateStakedBalance = (stakes: StakeData[]): BigNumberish => { @@ -64,6 +65,7 @@ export const stakingSlice = createSlice({ stakedBalance: 0, totalRewardsBalance: "0", totalBonusBalance: "0", + minStakeAmount: "0", } as StakingState, reducers: { updateState: (state, action: PayloadAction) => { @@ -215,6 +217,12 @@ export const stakingSlice = createSlice({ state.totalBonusBalance = calculateTotalBonusBalance(state.stakes) state.totalRewardsBalance = calculateTotalRewardsBalance(state) }, + setMinStake: ( + state: StakingState, + action: PayloadAction<{ amount: string }> + ) => { + state.minStakeAmount = action.payload.amount + }, }, }) @@ -224,4 +232,5 @@ export const { providerStaked, updateStakeAmountForProvider, unstaked, + setMinStake, } = stakingSlice.actions diff --git a/src/types/staking.ts b/src/types/staking.ts index 3cff2da5b..c0a31b68d 100644 --- a/src/types/staking.ts +++ b/src/types/staking.ts @@ -27,6 +27,7 @@ export interface UseStakingState { beneficiary: string authorizer: string updateState: (key: StakingStateKey, value: any) => UpdateState + minStakeAmount: string } } diff --git a/src/utils/forms.ts b/src/utils/forms.ts index 2aadbb6de..3757da7eb 100644 --- a/src/utils/forms.ts +++ b/src/utils/forms.ts @@ -9,7 +9,7 @@ type ValidationOptions = { lessThanValidationMsg: ValidationMsg requiredMsg: string } -const DEFAULT_MIN_VALUE = WeiPerEther.toString() +export const DEFAULT_MIN_VALUE = WeiPerEther.toString() const defaultLessThanMsg: ValidationMsg = (minAmount) => { return `The value should be less than or equal ${formatTokenAmount(