Skip to content

Commit

Permalink
refactor(explorer): move faucet from formik to react-hook-form
Browse files Browse the repository at this point in the history
  • Loading branch information
telestrial committed Dec 11, 2024
1 parent 71f03ca commit da74cd1
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 66 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-carrots-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'explorer': minor
---

Refactor explorer faucet from formik to react-hook-form.
146 changes: 80 additions & 66 deletions apps/explorer/components/Faucet/FaucetFundForm.tsx
Original file line number Diff line number Diff line change
@@ -1,94 +1,108 @@
import {
FormFieldFormik,
FormSubmitButtonFormik,
Button,
ConfigFields,
FieldSiacoin,
FieldText,
Paragraph,
triggerErrorToast,
triggerSuccessToast,
} from '@siafoundation/design-system'
import { toHastings } from '@siafoundation/units'
import { isValidAddress, toHastings } from '@siafoundation/units'
import BigNumber from 'bignumber.js'
import { useFormik } from 'formik'
import * as Yup from 'yup'
import { networkName } from '../../config'
import { useFaucetFund } from '../../hooks/useFaucetFund'
import { useForm } from 'react-hook-form'
import { Maybe } from '@siafoundation/types'

const initialValues = {
const defaultValues = {
address: '',
amount: undefined as BigNumber | undefined,
amount: undefined as Maybe<BigNumber> | undefined,
}

const validationSchema = Yup.object().shape({
address: Yup.string().required('Required'),
amount: Yup.string()
.required('Required')
.test(
'greater than zero',
'Must be greater than 0 SC',
(val) => !new BigNumber(val || 0).isZero()
)
.test('less than 1000', 'Must be 50,000 SC or less', (val) =>
new BigNumber(val || 0).lte(50_000)
),
})
const fields: ConfigFields<typeof defaultValues, never> = {
address: {
type: 'text',
title: 'Address',
placeholder: '020d48a57bc0...',
validation: {
required: 'An address is required',
validate: {
valid: (value: string) => {
return isValidAddress(value) || 'Invalid address'
},
},
},
},
amount: {
type: 'siacoin',
title: 'Amount',
showFiat: false,
validation: {
required: 'An amount is required',
validate: {
min: (value: Maybe<BigNumber>) =>
value?.gte(1) || 'Amount must be greater than 0',
max: (value: Maybe<BigNumber>) =>
value?.lte(50000) || 'Amount must be less than 50,000',
},
},
},
}

type Values = typeof defaultValues

type Props = {
onDone: (id: string) => void
}

export function FaucetFundForm({ onDone }: Props) {
const fund = useFaucetFund()

const formik = useFormik({
initialValues,
validationSchema,
onSubmit: async (values, actions) => {
const response = await fund.post({
payload: {
unlockHash: values.address,
amount: toHastings(values.amount || 0).toString(),
},
})
if (response.error) {
actions.setStatus({ error: response.error })
} else {
triggerSuccessToast({ title: 'Address has been funded' })
if (response.data) {
onDone(response.data.id)
}
actions.resetForm()
}
},
const form = useForm({
mode: 'all',
defaultValues,
})

const onSubmit = async (values: Values) => {
const response = await fund.post({
payload: {
unlockHash: values.address,
amount: toHastings(values.amount || 0).toString(),
},
})
if (response.error) {
const title =
'Fund request failed. ' +
(response.status === 400
? 'Check the address or try again later.'
: response.status === 429
? 'You have reached your request limits. Try again later.'
: 'Check your connection or try again later.')

triggerErrorToast({ title })
} else {
triggerSuccessToast({ title: 'Address has been funded.' })
if (response.data) onDone(response.data.id)
form.reset()
}
}

return (
<div className="flex flex-col gap-4">
<Paragraph size="14">
Fund a {networkName} wallet address with Siacoin.
</Paragraph>
<form onSubmit={formik.handleSubmit}>
<div className="flex flex-col gap-4">
<FormFieldFormik
formik={formik}
title="Address"
name="address"
placeholder="020d48a57bc0..."
autoComplete="off"
type="text"
variants={{
size: 'medium',
}}
/>
<FormFieldFormik
formik={formik}
title="Amount"
name="amount"
placeholder="100"
type="siacoin"
showFiat={false}
/>
<FormSubmitButtonFormik formik={formik} size="medium">
Fund wallet
</FormSubmitButtonFormik>
</div>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="flex flex-col gap-4"
>
<FieldText size="medium" name="address" form={form} fields={fields} />
<FieldSiacoin size="medium" name="amount" form={form} fields={fields} />
<Paragraph size="12" className="text-center">
Requests are limited to 5 per 5 minutes and 50,000 siacoins per day.
</Paragraph>
<Button size="medium" variant="accent" type="submit">
Fund wallet
</Button>
</form>
</div>
)
Expand Down

0 comments on commit da74cd1

Please sign in to comment.