Skip to content

Commit

Permalink
dev: ability to reset fee values in dev mode
Browse files Browse the repository at this point in the history
  • Loading branch information
theborakompanioni committed Nov 26, 2023
1 parent 224cd0e commit e9275a1
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 17 deletions.
4 changes: 2 additions & 2 deletions src/components/ToggleSwitch.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ChangeEvent } from 'react'
import { ReactNode, ChangeEvent } from 'react'
import styles from './ToggleSwitch.module.css'

interface ToggleSwitchProps {
label: string
label: string | ReactNode
subtitle?: string
onToggle: (isToggled: boolean) => void
toggledOn: boolean
Expand Down
86 changes: 71 additions & 15 deletions src/components/settings/FeeConfigModal.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { forwardRef, useRef, useCallback, useEffect, useState } from 'react'
import * as rb from 'react-bootstrap'
import { Trans, useTranslation } from 'react-i18next'
import { Formik, FormikErrors } from 'formik'
import { Formik, FormikErrors, FormikProps } from 'formik'
import classNames from 'classnames'
import { FEE_CONFIG_KEYS, TxFeeValueUnit, toTxFeeValueUnit, FeeValues, useLoadFeeConfigValues } from '../../hooks/Fees'
import { useUpdateConfigValues } from '../../context/ServiceConfigContext'
import { isValidNumber, factorToPercentage, percentageToFactor } from '../../utils'
import Sprite from '../Sprite'
import SegmentedTabs from '../SegmentedTabs'
import styles from './FeeConfigModal.module.css'
import { isDebugFeatureEnabled } from '../../constants/debugFeatures'
import ToggleSwitch from '../ToggleSwitch'

const __dev_allowFeeValuesReset = isDebugFeatureEnabled('allowFeeValuesReset')

type SatsPerKiloVByte = number

Expand Down Expand Up @@ -53,30 +57,56 @@ export type FeeConfigSectionKey = 'tx_fee' | 'cj_fee'
const TX_FEE_SECTION_KEY: FeeConfigSectionKey = 'tx_fee'
const CJ_FEE_SECTION_KEY: FeeConfigSectionKey = 'cj_fee'

type FeeFormValues = FeeValues & {
enableValidation?: boolean
}

interface FeeConfigFormProps {
initialValues: FeeValues
validate: (values: FeeValues, txFeesUnit: TxFeeValueUnit) => FormikErrors<FeeValues>
onSubmit: (values: FeeValues, txFeesUnit: TxFeeValueUnit) => void
initialValues: FeeFormValues
validate: (values: FeeFormValues, txFeesUnit: TxFeeValueUnit) => FormikErrors<FeeFormValues>
onSubmit: (values: FeeFormValues, txFeesUnit: TxFeeValueUnit) => void
defaultActiveSectionKey?: FeeConfigSectionKey
}

const FeeConfigForm = forwardRef(
(
{ onSubmit, validate, initialValues, defaultActiveSectionKey }: FeeConfigFormProps,
ref: React.Ref<HTMLFormElement>,
ref: React.Ref<FormikProps<FeeFormValues>>,
) => {
const { t, i18n } = useTranslation()

const [txFeesUnit, setTxFeesUnit] = useState<TxFeeValueUnit>(toTxFeeValueUnit(initialValues.tx_fees) || 'blocks')

return (
<Formik
innerRef={ref}
initialValues={initialValues}
validate={(values) => validate(values, txFeesUnit)}
onSubmit={(values) => onSubmit(values, txFeesUnit)}
>
{({ handleSubmit, setFieldValue, handleBlur, validateForm, values, touched, errors, isSubmitting }) => (
<rb.Form ref={ref} onSubmit={handleSubmit} noValidate lang={i18n.resolvedLanguage || i18n.language}>
<rb.Form onSubmit={handleSubmit} noValidate lang={i18n.resolvedLanguage || i18n.language}>
{__dev_allowFeeValuesReset && (
<div className="mb-4">
<ToggleSwitch
label={
<>
Enable form validation
<span className="ms-2 badge rounded-pill bg-warning">dev</span>
</>
}
subtitle={
'Ability to reset fee values to test what the UI looks like, when a user does not have these values configured.'
}
toggledOn={values.enableValidation ?? true}
onToggle={(isToggled) => {
setFieldValue('enableValidation', isToggled, true)
}}
disabled={isSubmitting}
/>
</div>
)}

<rb.Accordion flush defaultActiveKey={defaultActiveSectionKey}>
<rb.Accordion.Item eventKey={CJ_FEE_SECTION_KEY}>
<rb.Accordion.Header>
Expand Down Expand Up @@ -332,9 +362,9 @@ export default function FeeConfigModal({
const [isLoading, setIsLoading] = useState(true)
const [isSubmitting, setIsSubmitting] = useState(false)
const [loadError, setLoadError] = useState(false)
const [saveErrorMessage, setSaveErrorMessage] = useState<string | undefined>(undefined)
const [feeConfigValues, setFeeConfigValues] = useState<FeeValues | null>(null)
const formRef = useRef<HTMLFormElement>(null)
const [saveErrorMessage, setSaveErrorMessage] = useState<string>()
const [feeFormValues, setFeeFormValues] = useState<FeeFormValues | null>(null)
const formRef = useRef<FormikProps<FeeFormValues>>(null)

useEffect(() => {
setLoadError(false)
Expand All @@ -347,7 +377,7 @@ export default function FeeConfigModal({
.then((val) => {
if (abortCtrl.signal.aborted) return
setIsLoading(false)
setFeeConfigValues(val)
setFeeFormValues(val)
})
.catch((e) => {
if (abortCtrl.signal.aborted) return
Expand Down Expand Up @@ -415,8 +445,14 @@ export default function FeeConfigModal({
}

const validate = useCallback(
(values: FeeValues, txFeesUnit: TxFeeValueUnit) => {
const errors = {} as FormikErrors<FeeValues>
(values: FeeFormValues, txFeesUnit: TxFeeValueUnit) => {
const errors = {} as FormikErrors<FeeFormValues>

if (values.enableValidation === false) {
// do not validate form to enable resetting the values
// this can only be done in dev mode!
return errors
}

if (
!isValidNumber(values.tx_fees_factor) ||
Expand Down Expand Up @@ -536,10 +572,10 @@ export default function FeeConfigModal({
</>
) : (
<>
{feeConfigValues && (
{feeFormValues && (
<FeeConfigForm
ref={formRef}
initialValues={feeConfigValues}
initialValues={feeFormValues}
validate={validate}
onSubmit={submit}
defaultActiveSectionKey={defaultActiveSectionKey}
Expand All @@ -559,12 +595,32 @@ export default function FeeConfigModal({
<rb.Button variant="light" onClick={cancel} className="d-flex justify-content-center align-items-center">
{t('settings.fees.text_button_cancel')}
</rb.Button>

{__dev_allowFeeValuesReset && (
<rb.Button
variant="outline-dark"
className="position-relative"
onClick={() => {
formRef.current?.setFieldValue('max_cj_fee_abs', '', false)
formRef.current?.setFieldValue('max_cj_fee_rel', '', false)
formRef.current?.setFieldValue('tx_fees', '', false)
formRef.current?.setFieldValue('tx_fees_factor', '', false)
setTimeout(() => formRef.current?.validateForm(), 4)
}}
disabled={isLoading || isSubmitting}
>
Reset form values
<span className="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-warning">
dev
</span>
</rb.Button>
)}
<rb.Button
variant="dark"
type="submit"
className="d-flex justify-content-center align-items-center"
disabled={isLoading || isSubmitting}
onClick={() => formRef.current?.requestSubmit()}
onClick={() => formRef.current?.submitForm()}
>
{isSubmitting ? (
<>
Expand Down
2 changes: 2 additions & 0 deletions src/constants/debugFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ interface DebugFeatures {
devSetupPage: boolean
importDummyMnemonicPhrase: boolean
rescanChainPage: boolean
allowFeeValuesReset: boolean
fastThemeToggle: boolean
}

Expand All @@ -19,6 +20,7 @@ const debugFeatures: DebugFeatures = {
devSetupPage: devMode,
importDummyMnemonicPhrase: devMode,
rescanChainPage: devMode,
allowFeeValuesReset: devMode,
fastThemeToggle: devMode,
}

Expand Down

0 comments on commit e9275a1

Please sign in to comment.