From e9b449a3c611babf6e670ab4be73f4b6cf9b2dbb Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Thu, 16 Nov 2023 15:47:30 +0100 Subject: [PATCH 01/13] fix: improve input validation --- .../components/OtherParametersSection.tsx | 4 ++++ .../ManaCalculator/components/RoleSection.tsx | 6 ++++++ .../ManaCalculator/components/ValidatorCard.tsx | 6 ++++++ .../ManaCalculator/components/ValidatorSettings.tsx | 12 ++++++++++++ src/components/ManaCalculator/hooks/useManaState.ts | 5 +++++ 5 files changed, 33 insertions(+) diff --git a/src/components/ManaCalculator/components/OtherParametersSection.tsx b/src/components/ManaCalculator/components/OtherParametersSection.tsx index 5d60e49610d..47168441cc1 100644 --- a/src/components/ManaCalculator/components/OtherParametersSection.tsx +++ b/src/components/ManaCalculator/components/OtherParametersSection.tsx @@ -35,6 +35,8 @@ export function OtherParametersSection() { handleInitialEpochChange(Number(e.target.value))} > @@ -42,6 +44,8 @@ export function OtherParametersSection() { handleFinalEpochChange(Number(e.target.value))} > diff --git a/src/components/ManaCalculator/components/RoleSection.tsx b/src/components/ManaCalculator/components/RoleSection.tsx index 48c4bc26f21..b01b96f3d9a 100644 --- a/src/components/ManaCalculator/components/RoleSection.tsx +++ b/src/components/ManaCalculator/components/RoleSection.tsx @@ -37,6 +37,8 @@ export function RoleSection() { handleOwnHoldChange(toMicro(Number(e.target.value)))} > @@ -46,6 +48,8 @@ export function RoleSection() { handleOwnStakeChange(toMicro(Number(e.target.value))) @@ -72,6 +76,8 @@ export function RoleSection() { handleOwnStakeChange(toMicro(Number(e.target.value))) diff --git a/src/components/ManaCalculator/components/ValidatorCard.tsx b/src/components/ManaCalculator/components/ValidatorCard.tsx index 517a5293a46..d35772cd7b3 100644 --- a/src/components/ManaCalculator/components/ValidatorCard.tsx +++ b/src/components/ManaCalculator/components/ValidatorCard.tsx @@ -22,11 +22,14 @@ export function ValidatorCard({
Validator {id + 1}
handleStakeChange(toMicro(Number(e.target.value)), id)} > handleDelegatedStakeChange(toMicro(Number(e.target.value)), id) @@ -36,12 +39,15 @@ export function ValidatorCard({ className='col col--2 align-right horizontal-spaced' type='number' step='0.01' + min='0' + max='1' value={validator.performanceFactor} onChange={(e) => handlePFChange(Number(e.target.value), id)} > handleFCChange(Number(e.target.value), id)} diff --git a/src/components/ManaCalculator/components/ValidatorSettings.tsx b/src/components/ManaCalculator/components/ValidatorSettings.tsx index 95be4df6508..f8c6e951ded 100644 --- a/src/components/ManaCalculator/components/ValidatorSettings.tsx +++ b/src/components/ManaCalculator/components/ValidatorSettings.tsx @@ -27,6 +27,8 @@ export function ValidatorSettings() { Fixed costs handleShareOfYourStakeLockedChange(Number(e.target.value)) } @@ -56,6 +62,8 @@ export function ValidatorSettings() { handleAttractedNewDelegatedStakeChange(Number(e.target.value)) @@ -67,6 +75,10 @@ export function ValidatorSettings() { handleAttractedDelegatedStakeFromOtherPoolsChange( diff --git a/src/components/ManaCalculator/hooks/useManaState.ts b/src/components/ManaCalculator/hooks/useManaState.ts index 92f5c47b90c..167475f72ce 100644 --- a/src/components/ManaCalculator/hooks/useManaState.ts +++ b/src/components/ManaCalculator/hooks/useManaState.ts @@ -64,6 +64,7 @@ export function useGivenManaState( } function handlePFChange(value: number, id: number) { + if (value < 0 || value > 1) return; setState({ ...state, validators: state.validators.map((validator, i) => { @@ -88,6 +89,7 @@ export function useGivenManaState( } function handleOwnStakeChange(value: number) { + if (value > state.heldTokens) return; setState({ ...state, [getStakedOrDelegated(state.userType)]: value, @@ -109,6 +111,7 @@ export function useGivenManaState( } function handleOwnPFChange(value: number) { + if (value < 0 || value > 1) return; setState({ ...state, validator: { ...state.validator, performanceFactor: value }, @@ -147,6 +150,7 @@ export function useGivenManaState( } function handleInitialEpochChange(value: number) { + if (value > state.finalEpoch) return; setState({ ...state, initialEpoch: value, @@ -154,6 +158,7 @@ export function useGivenManaState( } function handleFinalEpochChange(value: number) { + if (state.initialEpoch > value) return; setState({ ...state, finalEpoch: value, From 8ab5c579aecae10a03cdb9b50ca9d45d7a875288 Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Wed, 22 Nov 2023 17:49:17 +0100 Subject: [PATCH 02/13] fix: add minimum amount to missing inputs --- src/components/ManaCalculator/components/DelegatorSettings.tsx | 2 ++ src/components/ManaCalculator/components/ValidatorSettings.tsx | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/components/ManaCalculator/components/DelegatorSettings.tsx b/src/components/ManaCalculator/components/DelegatorSettings.tsx index 37c8f0f3f10..5f4596d6d25 100644 --- a/src/components/ManaCalculator/components/DelegatorSettings.tsx +++ b/src/components/ManaCalculator/components/DelegatorSettings.tsx @@ -32,6 +32,8 @@ export function DelegatorSettings() { handleOwnStakeChange(toMicro(Number(e.target.value)))} > diff --git a/src/components/ManaCalculator/components/ValidatorSettings.tsx b/src/components/ManaCalculator/components/ValidatorSettings.tsx index 8f980daa3fa..73c24a8eb14 100644 --- a/src/components/ManaCalculator/components/ValidatorSettings.tsx +++ b/src/components/ManaCalculator/components/ValidatorSettings.tsx @@ -21,6 +21,8 @@ export function ValidatorSettings() { handleOwnStakeChange(toMicro(Number(e.target.value)))} > From 626746cefa03ac39440c1fd32ae98ee1a3161055 Mon Sep 17 00:00:00 2001 From: JCNoguera Date: Tue, 28 Nov 2023 14:04:15 +0100 Subject: [PATCH 03/13] feat: improve input validation in ManaCalculator --- .../components/DelegatorSettings.tsx | 13 +-- .../components/ManaCalculatorInput.tsx | 78 +++++++++++++++ .../components/OtherParametersSection.tsx | 20 ++-- .../ManaCalculator/components/RoleSection.tsx | 16 ++-- .../components/ValidatorCard.tsx | 73 +++++++------- .../components/ValidatorSettings.tsx | 49 +++++----- .../ManaCalculator/components/index.ts | 1 + .../ManaCalculator/hooks/useManaState.ts | 94 +++++++++++++------ src/components/ManaCalculator/styles.css | 36 +++++++ 9 files changed, 271 insertions(+), 109 deletions(-) create mode 100644 src/components/ManaCalculator/components/ManaCalculatorInput.tsx diff --git a/src/components/ManaCalculator/components/DelegatorSettings.tsx b/src/components/ManaCalculator/components/DelegatorSettings.tsx index 5f4596d6d25..cb6f803c2dc 100644 --- a/src/components/ManaCalculator/components/DelegatorSettings.tsx +++ b/src/components/ManaCalculator/components/DelegatorSettings.tsx @@ -1,8 +1,9 @@ import React from 'react'; import { Details } from '@docusaurus/theme-common/Details'; import { useManaState } from '../hooks'; -import { fromMicro, toMicro } from '../utils'; +import { fromMicro } from '../utils'; import Select from 'react-select'; +import { ManaCalculatorInput } from '.'; export function DelegatorSettings() { const { state, handleOwnStakeChange, handleValidatorChange } = useManaState(); @@ -30,13 +31,13 @@ export function DelegatorSettings() { - handleOwnStakeChange(toMicro(Number(e.target.value)))} - > + min={0} + max={fromMicro(state.heldTokens)} + onChange={handleOwnStakeChange} + /> ); } diff --git a/src/components/ManaCalculator/components/ManaCalculatorInput.tsx b/src/components/ManaCalculator/components/ManaCalculatorInput.tsx new file mode 100644 index 00000000000..d7dcc97d9a9 --- /dev/null +++ b/src/components/ManaCalculator/components/ManaCalculatorInput.tsx @@ -0,0 +1,78 @@ +import React, { JSX, useEffect, useState } from 'react'; + +interface IManaCalculatorCustomInput { + value: string | number; + onChange: (value: string) => void; + className?: string; + min?: number; + max?: number; +} + +export function ManaCalculatorInput({ + value, + onChange, + className, + min, + max, +}: IManaCalculatorCustomInput): JSX.Element { + const [errorMessage, setErrorMessage] = useState(''); + const [inputValue, setInputValue] = useState(value); + + useEffect(() => { + try { + verifyMinAndMax(value); + } catch (error) { + setErrorMessage(error.message); + } + }, [min, max]); + + function verifyMinAndMax(value: string | number) { + let message = ''; + + if (!isNaN(min) && Number(value) < min) { + message = 'Minimum value is ' + min; + } + if (!isNaN(min) && Number(value) > max) { + message = 'Maximum value is ' + max; + } + + if ( + !isNaN(min) && + !isNaN(max) && + (Number(value) < min || Number(value) > max) + ) { + message = 'Min: ' + min + ', Max: ' + max; + } + if (message) { + throw new Error(message); + } + } + + function handleInputChange(e: React.ChangeEvent) { + try { + setInputValue(e.target.value); + verifyMinAndMax(e.target.value); + setErrorMessage(''); + onChange(e.target.value); + } catch (error) { + setErrorMessage(error.message); + } + } + + return ( +
+ + {errorMessage &&

{errorMessage}

} +
+ ); +} diff --git a/src/components/ManaCalculator/components/OtherParametersSection.tsx b/src/components/ManaCalculator/components/OtherParametersSection.tsx index 67626b4e20c..1211d6848f2 100644 --- a/src/components/ManaCalculator/components/OtherParametersSection.tsx +++ b/src/components/ManaCalculator/components/OtherParametersSection.tsx @@ -4,6 +4,7 @@ import Select from 'react-select'; import { UserType } from '../enums'; import { CongestionType } from '../enums'; import { AdvancedSettingsValidator } from './AdvancedSettingsValidator'; +import { ManaCalculatorInput } from '.'; export function OtherParametersSection() { const { @@ -34,22 +35,21 @@ export function OtherParametersSection() { />
- handleInitialEpochChange(Number(e.target.value))} - > + onChange={handleInitialEpochChange} + />
- handleFinalEpochChange(Number(e.target.value))} - > + onChange={handleFinalEpochChange} + /> {state.userType === UserType.HOLDER ? ( <> ) : ( diff --git a/src/components/ManaCalculator/components/RoleSection.tsx b/src/components/ManaCalculator/components/RoleSection.tsx index 8367a8a7677..45e554e6eca 100644 --- a/src/components/ManaCalculator/components/RoleSection.tsx +++ b/src/components/ManaCalculator/components/RoleSection.tsx @@ -2,12 +2,14 @@ import React from 'react'; import { useManaState } from '../hooks'; import Select from 'react-select'; import { UserType } from '../enums'; -import { fromMicro, toMicro } from '../utils'; +import { fromMicro } from '../utils'; import { ValidatorSettings } from './ValidatorSettings'; import { DelegatorSettings } from './DelegatorSettings'; +import { ManaCalculatorInput } from '.'; export function RoleSection() { - const { state, handleUserChange, handleOwnHoldChange } = useManaState(); + const { state, handleUserChange, handleOwnHoldChange, maxTotalSupply } = + useManaState(); return (

Role configuration

@@ -27,13 +29,13 @@ export function RoleSection() { />
- handleOwnHoldChange(toMicro(Number(e.target.value)))} - > + onChange={handleOwnHoldChange} + />
{state.userType === UserType.VALIDATOR ? ( diff --git a/src/components/ManaCalculator/components/ValidatorCard.tsx b/src/components/ManaCalculator/components/ValidatorCard.tsx index d35772cd7b3..23b95d2cd77 100644 --- a/src/components/ManaCalculator/components/ValidatorCard.tsx +++ b/src/components/ManaCalculator/components/ValidatorCard.tsx @@ -1,7 +1,8 @@ import React from 'react'; import { useManaState } from '../hooks'; import { ValidatorProps } from '../types'; -import { fromMicro, toMicro } from '../utils'; +import { fromMicro } from '../utils'; +import { ManaCalculatorInput } from '.'; export function ValidatorCard({ validator, @@ -16,42 +17,48 @@ export function ValidatorCard({ handleDelegatedStakeChange, handlePFChange, handleFCChange, + maxTotalSupply, } = useManaState(); + return ( <>
Validator {id + 1}
- handleStakeChange(toMicro(Number(e.target.value)), id)} - > - - handleDelegatedStakeChange(toMicro(Number(e.target.value)), id) - } - > - handlePFChange(Number(e.target.value), id)} - > - handleFCChange(Number(e.target.value), id)} - > +
+ handleStakeChange(value, id)} + /> +
+
+ handleDelegatedStakeChange(value, id)} + /> +
+
+ handlePFChange(value, id)} + /> +
+
+ handleFCChange(value, id)} + /> +