Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve input validation from ManaCalculator #1337

Merged
merged 15 commits into from
Dec 8, 2023
13 changes: 7 additions & 6 deletions src/components/ManaCalculator/components/DelegatorSettings.tsx
Original file line number Diff line number Diff line change
@@ -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();
Expand Down Expand Up @@ -30,13 +31,13 @@ export function DelegatorSettings() {
<label className='inlined-label'>
Delegated amount ({state.network})
</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact inlined'
type='number'
min='0'
value={fromMicro(state.stakedOrDelegatedTokens)}
onChange={(e) => handleOwnStakeChange(toMicro(Number(e.target.value)))}
></input>
min={0}
max={fromMicro(state.heldTokens)}
onChange={handleOwnStakeChange}
/>
</Details>
);
}
78 changes: 78 additions & 0 deletions src/components/ManaCalculator/components/ManaCalculatorInput.tsx
Original file line number Diff line number Diff line change
@@ -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({
begonaalvarezd marked this conversation as resolved.
Show resolved Hide resolved
value,
onChange,
className,
min,
max,
}: IManaCalculatorCustomInput): JSX.Element {
const [errorMessage, setErrorMessage] = useState<string>('');
const [inputValue, setInputValue] = useState<string | number>(value);
marc2332 marked this conversation as resolved.
Show resolved Hide resolved

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<HTMLInputElement>) {
try {
setInputValue(e.target.value);
verifyMinAndMax(e.target.value);
setErrorMessage('');
onChange(e.target.value);
} catch (error) {
setErrorMessage(error.message);
}
}

return (
<div
className={`mana_calculator__custom_wrapper ${
errorMessage ? 'errored' : ''
}`}
>
<input
className={className}
min={min}
max={max}
value={inputValue}
onChange={handleInputChange}
/>
{errorMessage && <p className='mana_calculator__error'>{errorMessage}</p>}
</div>
);
}
20 changes: 10 additions & 10 deletions src/components/ManaCalculator/components/OtherParametersSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -34,22 +35,21 @@ export function OtherParametersSection() {
/>
<br />
<label className='inlined-label'>Initial epoch</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact inlined'
type='number'
min='0'
min={1}
max={state.finalEpoch}
value={state.initialEpoch}
onChange={(e) => handleInitialEpochChange(Number(e.target.value))}
></input>
onChange={handleInitialEpochChange}
/>
<br />
<label className='inlined-label'>Final epoch</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact inlined'
type='number'
min={state.initialEpoch + 1}
min={state.initialEpoch}
value={state.finalEpoch}
onChange={(e) => handleFinalEpochChange(Number(e.target.value))}
></input>
onChange={handleFinalEpochChange}
/>
{state.userType === UserType.HOLDER ? (
<></>
) : (
Expand Down
16 changes: 9 additions & 7 deletions src/components/ManaCalculator/components/RoleSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
begonaalvarezd marked this conversation as resolved.
Show resolved Hide resolved
<div className='mana_calculator__card'>
<h4>Role configuration</h4>
Expand All @@ -27,13 +29,13 @@ export function RoleSection() {
/>
<br />
<label className='inlined-label'>Owned amount ({state.network})</label>
<input
<ManaCalculatorInput
min={0}
max={maxTotalSupply}
Dr-Electron marked this conversation as resolved.
Show resolved Hide resolved
className='mana_calculator__compact inlined'
type='number'
min='0'
value={fromMicro(state.heldTokens)}
onChange={(e) => handleOwnHoldChange(toMicro(Number(e.target.value)))}
></input>
onChange={handleOwnHoldChange}
/>
<br />
{state.userType === UserType.VALIDATOR ? (
<ValidatorSettings />
Expand Down
73 changes: 40 additions & 33 deletions src/components/ManaCalculator/components/ValidatorCard.tsx
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -16,42 +17,48 @@ export function ValidatorCard({
handleDelegatedStakeChange,
handlePFChange,
handleFCChange,
maxTotalSupply,
} = useManaState();

return (
<>
<div className='col col--2'>Validator {id + 1}</div>
<input
className='col col--2 align-right horizontal-spaced'
type='number'
min='0'
value={fromMicro(validator.lockedStake)}
onChange={(e) => handleStakeChange(toMicro(Number(e.target.value)), id)}
></input>
<input
className='col col--2 align-right horizontal-spaced'
type='number'
value={fromMicro(validator.delegatedStake)}
onChange={(e) =>
handleDelegatedStakeChange(toMicro(Number(e.target.value)), id)
}
></input>
<input
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)}
></input>
<input
className='col col--2 align-right horizontal-spaced'
type='number'
min='0'
step='0.01'
value={validator.fixedCost}
onChange={(e) => handleFCChange(Number(e.target.value), id)}
></input>
<div className='validator_card col col--2 align-right horizontal-spaced'>
<ManaCalculatorInput
className='w-full'
min={0}
max={maxTotalSupply}
value={fromMicro(validator.lockedStake)}
onChange={(value: string) => handleStakeChange(value, id)}
/>
</div>
<div className='validator_card col col--2 align-right horizontal-spaced'>
<ManaCalculatorInput
className='w-full'
min={0}
max={maxTotalSupply}
value={fromMicro(validator.delegatedStake)}
onChange={(value: string) => handleDelegatedStakeChange(value, id)}
/>
</div>
Dr-Electron marked this conversation as resolved.
Show resolved Hide resolved
<div className='validator_card col col--2 align-right horizontal-spaced'>
<ManaCalculatorInput
className='w-full'
min={0}
max={1}
value={validator.performanceFactor}
onChange={(value: string) => handlePFChange(value, id)}
/>
</div>
<div className='validator_card col col--2 align-right horizontal-spaced'>
<ManaCalculatorInput
className='w-full'
min={0}
max={Number.MAX_SAFE_INTEGER}
value={validator.fixedCost}
onChange={(value: string) => handleFCChange(value, id)}
/>
</div>
<button
className=' button button--remove mana-calculator__button mana-calculator__transparent-button'
onClick={() => handleDelete(id)}
Expand Down
49 changes: 23 additions & 26 deletions src/components/ManaCalculator/components/ValidatorSettings.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import { Details } from '@docusaurus/theme-common/Details';
import { useManaState } from '../hooks';
import { fromMicro, toMicro, roundMax } from '../utils';
import { fromMicro, roundMax } from '../utils';
import { ManaCalculatorInput } from '.';

export function ValidatorSettings() {
const {
Expand All @@ -10,6 +11,7 @@ export function ValidatorSettings() {
handleOwnFCChange,
handleOwnStakeChange,
handleAttractedNewDelegatedStakeChange,
maxTotalSupply,
} = useManaState();
return (
<Details
Expand All @@ -19,49 +21,44 @@ export function ValidatorSettings() {
<label className='inlined-long-label'>
Staked amount ({state.network})
</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact inlined'
type='number'
min='0'
min={0}
max={fromMicro(state.heldTokens)}
value={fromMicro(state.stakedOrDelegatedTokens)}
onChange={(e) => handleOwnStakeChange(toMicro(Number(e.target.value)))}
></input>
onChange={handleOwnStakeChange}
/>
<br />
<label className='inlined-long-label'>Performance factor</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact input--vertical-spaced'
min='0'
max='1'
type='number'
step='0.01'
min={0}
max={1}
value={state.validator.performanceFactor}
onChange={(e) => handleOwnPFChange(Number(e.target.value))}
></input>
onChange={handleOwnPFChange}
/>
<br />
<label className='inlined-long-label'>Fixed costs</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact input--vertical-spaced'
min='0'
type='number'
step='0.01'
min={0}
max={Number.MAX_SAFE_INTEGER}
value={state.validator.fixedCost}
onChange={(e) => handleOwnFCChange(Number(e.target.value))}
></input>
onChange={handleOwnFCChange}
/>
<label className='inlined-long-label'>
Attracted new delegated stake ({state.network})
</label>
<input
<ManaCalculatorInput
className='mana_calculator__compact input--vertical-spaced'
type='number'
min='0'
min={0}
max={maxTotalSupply}
value={roundMax(
fromMicro(state.validator.attractedNewDelegatedStake),
0,
)}
onChange={(e) =>
handleAttractedNewDelegatedStakeChange(Number(e.target.value))
}
></input>
onChange={handleAttractedNewDelegatedStakeChange}
></ManaCalculatorInput>
</Details>
);
}
1 change: 1 addition & 0 deletions src/components/ManaCalculator/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from './RoleSection';
export * from './OutputForm';
export * from './NetworkSection';
export * from './ManaAcculation';
export * from './ManaCalculatorInput';
Loading
Loading