Skip to content

Commit

Permalink
Merge pull request #118 from threshold-network/min-stake-validation
Browse files Browse the repository at this point in the history
Minimum Stake validation

This PR adds validation to the staking form. To stake in T network the minimum 
stake amount is required. Currently it is 40,000 T.

Main changes:

- set the placeholder for input in staking form- Minimum stake <amount> T,
- create a hook that returns the min stake amount- it fetches the min stake 
amount if needed and saves in a redux store. If a value already exists in redux 
store a hook will return a value from redux store, otherwise fetches the value 
from chain,
- update the TokenAmountForm - allow to set the placeholder for an input and set
the required minimum amount to submit a form.
  • Loading branch information
michalsmiarowski authored Jun 1, 2022
2 parents 184639b + d0d368f commit 16a4dbb
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 4 deletions.
15 changes: 12 additions & 3 deletions src/components/Forms/TokenAmountForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand All @@ -25,6 +29,8 @@ type TokenAmountFormProps = {
shouldDisplayMaxAmountInLabel?: boolean
token?: { decimals: number; symbol: string }
innerRef?: Ref<FormikProps<FormValues>>
placeholder?: string
minTokenAmount?: string | number
}

const TokenAmountFormBase: FC<
Expand All @@ -39,6 +45,7 @@ const TokenAmountFormBase: FC<
isDisabled = false,
shouldValidateForm = true,
shouldDisplayMaxAmountInLabel = false,
placeholder,
...formikProps
}) => {
return (
Expand All @@ -60,7 +67,7 @@ const TokenAmountFormBase: FC<
label
)
}
placeholder={`${token.symbol} amount`}
placeholder={placeholder || `${token.symbol} amount`}
icon={icon}
mb={2}
max={maxTokenAmount}
Expand Down Expand Up @@ -88,7 +95,8 @@ export const TokenAmountForm = withFormik<TokenAmountFormProps, FormValues>({

errors.tokenAmount = validateAmountInRange(
values.tokenAmount,
props.maxTokenAmount.toString()
props.maxTokenAmount.toString(),
props.minTokenAmount ? props.minTokenAmount.toString() : DEFAULT_MIN_VALUE
)
return getErrorsObj(errors)
},
Expand All @@ -100,4 +108,5 @@ export const TokenAmountForm = withFormik<TokenAmountFormProps, FormValues>({

TokenAmountForm.defaultProps = {
shouldValidateForm: true,
minTokenAmount: DEFAULT_MIN_VALUE,
}
25 changes: 25 additions & 0 deletions src/hooks/useMinStakeAmount.ts
Original file line number Diff line number Diff line change
@@ -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
}
8 changes: 8 additions & 0 deletions src/pages/Staking/StakedPortfolioCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<ComponentProps<typeof Card>> = (props) => {
const { openModal } = useModal()
const tBalance = useTokenBalance(Token.T)
const minStakeAmount = useMinStakeAmount()

const openStakingModal = async (stakeAmount: string) => {
openModal(ModalType.StakingChecklist, { stakeAmount })
Expand Down Expand Up @@ -47,6 +49,12 @@ const StakedPortfolioCard: FC<ComponentProps<typeof Card>> = (props) => {
label="Stake Amount"
submitButtonText="Stake"
maxTokenAmount={tBalance}
placeholder={`Minimum stake ${
minStakeAmount === "0"
? "loading..."
: `${formatTokenAmount(minStakeAmount)} T`
}`}
minTokenAmount={minStakeAmount}
/>
<StakingContractLearnMore mt="3" />
</Card>
Expand Down
9 changes: 9 additions & 0 deletions src/store/staking/stakingSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ interface StakingState {
stakedBalance: BigNumberish
totalRewardsBalance: string
totalBonusBalance: string
minStakeAmount: string
}

const calculateStakedBalance = (stakes: StakeData[]): BigNumberish => {
Expand Down Expand Up @@ -64,6 +65,7 @@ export const stakingSlice = createSlice({
stakedBalance: 0,
totalRewardsBalance: "0",
totalBonusBalance: "0",
minStakeAmount: "0",
} as StakingState,
reducers: {
updateState: (state, action: PayloadAction<UpdateStateActionPayload>) => {
Expand Down Expand Up @@ -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
},
},
})

Expand All @@ -224,4 +232,5 @@ export const {
providerStaked,
updateStakeAmountForProvider,
unstaked,
setMinStake,
} = stakingSlice.actions
1 change: 1 addition & 0 deletions src/types/staking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface UseStakingState {
beneficiary: string
authorizer: string
updateState: (key: StakingStateKey, value: any) => UpdateState
minStakeAmount: string
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/utils/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit 16a4dbb

Please sign in to comment.