Skip to content

Commit

Permalink
Merge pull request #643 from threshold-network/feature/staking-form-u…
Browse files Browse the repository at this point in the history
…x-improvements

Improve staking form user experience

Ref: #634

Added validation if user wallet is empty, simplified and made validation error
messages more descriptive, improved readability of validation function, disabled
form if wallet is not connected.

Some of the issues were also addressed in
#666, which was merged
into this PR.
  • Loading branch information
michalsmiarowski authored Nov 21, 2023
2 parents e6ed52e + 15bb0d8 commit 462be69
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 47 deletions.
14 changes: 7 additions & 7 deletions src/components/Forms/TokenAmountForm.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import { BodySm, Box, ButtonProps, Icon } from "@threshold-network/components"
import { FormikErrors, FormikProps, withFormik } from "formik"
import { FC, Ref } from "react"
import { Icon, Box, ButtonProps, BodySm } from "@threshold-network/components"
import { withFormik, FormikProps, FormikErrors } from "formik"
import ThresholdCircleBrand from "../../static/icons/ThresholdCircleBrand"
import { FormikTokenBalanceInput } from "./FormikTokenBalanceInput"
import SubmitTxButton from "../SubmitTxButton"
import { Form } from "./Form"
import { formatTokenAmount } from "../../utils/formatAmount"
import {
DEFAULT_MIN_VALUE,
getErrorsObj,
validateAmountInRange,
} from "../../utils/forms"
import { formatTokenAmount } from "../../utils/formatAmount"
import SubmitTxButton from "../SubmitTxButton"
import { Form } from "./Form"
import { FormikTokenBalanceInput } from "./FormikTokenBalanceInput"

export type FormValues = {
tokenAmount: string
Expand Down Expand Up @@ -71,7 +71,7 @@ export const TokenAmountFormBase: FC<
max={maxTokenAmount}
helperText={helperText}
isDisabled={isDisabled}
_disabled={{ bg: "gray.50", border: "none" }}
_disabled={{ bg: "gray.50", border: "none", cursor: "not-allowed" }}
/>
<SubmitTxButton
type="submit"
Expand Down
30 changes: 15 additions & 15 deletions src/components/StakingApplicationForms/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { FC, Ref, useEffect, useState } from "react"
import { BodyMd, BodySm } from "@threshold-network/components"
import { BigNumber } from "ethers"
import { FormikErrors, FormikProps, withFormik } from "formik"
import { BodyMd, BodySm } from "@threshold-network/components"
import {
TokenAmountFormBase,
TokenAmountFormBaseProps,
FormValues,
} from "../Forms"
import { FC, Ref, useEffect, useState } from "react"
import { formatTokenAmount } from "../../utils/formatAmount"
import {
defaultLessThanMsg,
defaultValidationOptions,
defaultLessThanMessage,
defaultAmountValidationOptions,
DEFAULT_MIN_VALUE,
getErrorsObj,
validateAmountInRange,
} from "../../utils/forms"
import { formatTokenAmount } from "../../utils/formatAmount"
import {
FormValues,
TokenAmountFormBase,
TokenAmountFormBaseProps,
} from "../Forms"

type ComponentProps = {
totalStake: string
Expand Down Expand Up @@ -148,11 +148,11 @@ const deauthorizationValidation = (
max.toString(),
DEFAULT_MIN_VALUE,
{
...defaultValidationOptions,
lessThanValidationMsg(amount) {
return `${defaultLessThanMsg(amount)} or equal to ${formatTokenAmount(
authorizedAmount.toString()
)} T`
...defaultAmountValidationOptions,
lessThanValidationMessage(amount) {
return `${defaultLessThanMessage(
amount
)} or equal to ${formatTokenAmount(authorizedAmount.toString())} T`
},
}
)
Expand Down
1 change: 1 addition & 0 deletions src/components/SubmitTxButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ const SubmitTxButton: FC<Props> = ({
onClick={() => openModal(ModalType.SelectWallet)}
{...buttonProps}
type="button"
isDisabled={false}
>
Connect Wallet
</Button>
Expand Down
3 changes: 3 additions & 0 deletions src/pages/Staking/NewStakeCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import { useMinStakeAmount } from "../../hooks/useMinStakeAmount"
import { useModal } from "../../hooks/useModal"
import { useTokenBalance } from "../../hooks/useTokenBalance"
import { formatTokenAmount } from "../../utils/formatAmount"
import { useWeb3React } from "@web3-react/core"

const NewStakeCard: FC<ComponentProps<typeof Card>> = () => {
const { openModal } = useModal()
const tBalance = useTokenBalance(Token.T)
const { minStakeAmount, isLoading, hasError } = useMinStakeAmount()
const { active } = useWeb3React()

const openStakingModal = async (stakeAmount: string) => {
openModal(ModalType.StakingChecklist, { stakeAmount })
Expand Down Expand Up @@ -39,6 +41,7 @@ const NewStakeCard: FC<ComponentProps<typeof Card>> = () => {
maxTokenAmount={tBalance}
placeholder={placeholder}
minTokenAmount={minStakeAmount}
isDisabled={!active}
/>
<StakingContractLearnMore mt="3" />
</Card>
Expand Down
72 changes: 47 additions & 25 deletions src/utils/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,57 +10,79 @@ import { isAddress, isAddressZero } from "../web3/utils"
import { formatTokenAmount } from "./formatAmount"
import { getBridgeBTCSupportedAddressPrefixesText } from "./tBTC"

type ValidationMsg = string | ((amount: string) => string)
type ValidationOptions = {
greaterThanValidationMsg: ValidationMsg
lessThanValidationMsg: ValidationMsg
requiredMsg: string
type AmountValidationMessage = string | ((amount: string) => string)
type AmountValidationOptions = {
greaterThanValidationMessage: AmountValidationMessage
lessThanValidationMessage: AmountValidationMessage
requiredMessage: string
insufficientBalanceMessage: string
}
export const DEFAULT_MIN_VALUE = WeiPerEther.toString()

export const defaultLessThanMsg: (minAmount: string) => string = (
minAmount
export const defaultLessThanMessage: (maxAmount: string) => string = (
maxAmount
) => {
return `The value should be less than or equal ${formatTokenAmount(
minAmount
maxAmount
)}`
}

export const defaultGreaterThanMsg: (minAmount: string) => string = (
maxAmount
export const defaultGreaterThanMessage: (minAmount: string) => string = (
minAmount
) => {
return `The value should be greater than or equal ${formatTokenAmount(
maxAmount
minAmount
)}`
}
export const defaultValidationOptions: ValidationOptions = {
greaterThanValidationMsg: defaultGreaterThanMsg,
lessThanValidationMsg: defaultLessThanMsg,
requiredMsg: "Required",
export const defaultAmountValidationOptions: AmountValidationOptions = {
greaterThanValidationMessage: defaultGreaterThanMessage,
lessThanValidationMessage: defaultLessThanMessage,
requiredMessage: "Required.",
insufficientBalanceMessage: "Your wallet balance is insufficient.",
}

const getAmountInRangeValidationMessage = (
validationMessage: AmountValidationMessage,
value: string
) => {
return typeof validationMessage === "function"
? validationMessage(value)
: validationMessage
}

export const validateAmountInRange = (
value: string,
maxValue: string,
minValue = DEFAULT_MIN_VALUE,
options: ValidationOptions = defaultValidationOptions
options: AmountValidationOptions = defaultAmountValidationOptions
) => {
if (!value) {
return options.requiredMsg
return options.requiredMessage
}

const valueInBN = BigNumber.from(value)
const maxValueInBN = BigNumber.from(maxValue)
const minValueInBN = BigNumber.from(minValue)

if (valueInBN.gt(maxValueInBN)) {
return typeof options.lessThanValidationMsg === "function"
? options.lessThanValidationMsg(maxValue)
: options.lessThanValidationMsg
} else if (valueInBN.lt(minValueInBN)) {
return typeof options.greaterThanValidationMsg === "function"
? options.greaterThanValidationMsg(minValue)
: options.greaterThanValidationMsg
const isBalanceInsufficient = maxValueInBN.isZero()
const isMaximumValueExceeded = valueInBN.gt(maxValueInBN)
const isMinimumValueFulfilled = valueInBN.gte(minValueInBN)

if (!isMinimumValueFulfilled) {
return getAmountInRangeValidationMessage(
options.greaterThanValidationMessage,
minValue
)
}
if (isBalanceInsufficient) {
return options.insufficientBalanceMessage
}

if (isMaximumValueExceeded) {
return getAmountInRangeValidationMessage(
options.lessThanValidationMessage,
maxValue
)
}
}

Expand Down

0 comments on commit 462be69

Please sign in to comment.