allow nym node config updates (#5066)

This commit is contained in:
Fouad
2024-10-31 09:59:22 +00:00
committed by GitHub
parent c90ebf0a6a
commit 8b0b70a727
7 changed files with 85 additions and 48 deletions
@@ -3,7 +3,7 @@ import { CurrencyDenom } from '@nymproject/types';
import { TBondNymNodeArgs, TBondMixNodeArgs } from 'src/types';
const defaultNymNodeValues: TBondNymNodeArgs['nymnode'] = {
identity_key: 'H6rXWgsW89QsVyaNSS3qBe9zZFLhBS6Gn3YRkGFSoFW9',
identity_key: '',
custom_http_port: null,
host: '1.1.1.1',
};
@@ -1,31 +1,12 @@
import React from 'react';
import * as yup from 'yup';
import * as Yup from 'yup';
import { Stack, TextField, FormControlLabel, Checkbox } from '@mui/material';
import { useForm } from 'react-hook-form';
import { IdentityKeyFormField } from '@nymproject/react/mixnodes/IdentityKeyFormField';
import { yupResolver } from '@hookform/resolvers/yup';
import { isValidHostname, validateRawPort } from 'src/utils';
import { SimpleModal } from 'src/components/Modals/SimpleModal';
import { useFormContext } from './FormContext';
const yupValidationSchema = yup.object().shape({
identity_key: yup.string().required('Identity key is required'),
host: yup
.string()
.required('A host is required')
.test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || ''))
.test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)),
custom_http_port: yup
.number()
.nullable()
.test('valid-http', 'A valid http port is required', (value) => {
if (value === null) {
return true;
}
return value ? validateRawPort(value) : false;
}),
});
import { settingsValidationSchema } from './settingsValidationSchema';
type NymNodeDataProps = {
onClose: () => void;
@@ -34,6 +15,11 @@ type NymNodeDataProps = {
step: number;
};
const validationSchema = Yup.object().shape({
identity_key: Yup.string().required('Identity key is required'),
...settingsValidationSchema.fields,
});
const NymNodeData = ({ onClose, onNext, step }: NymNodeDataProps) => {
const { setNymNodeData, nymNodeData } = useFormContext();
const {
@@ -44,7 +30,7 @@ const NymNodeData = ({ onClose, onNext, step }: NymNodeDataProps) => {
} = useForm({
mode: 'all',
defaultValues: nymNodeData,
resolver: yupResolver(yupValidationSchema),
resolver: yupResolver(validationSchema),
});
const [showAdvancedOptions, setShowAdvancedOptions] = React.useState(false);
@@ -0,0 +1,20 @@
import { isValidHostname, validateRawPort } from 'src/utils';
import * as Yup from 'yup';
const settingsValidationSchema = Yup.object().shape({
host: Yup.string()
.required('A host is required')
.test('no-whitespace', 'Host cannot contain whitespace', (value) => !/\s/.test(value || ''))
.test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)),
custom_http_port: Yup.number()
.nullable()
.test('valid-http', 'A valid http port is required', (value) => {
if (value === null) {
return true;
}
return value ? validateRawPort(value) : false;
}),
});
export { settingsValidationSchema };
+26
View File
@@ -21,6 +21,7 @@ import {
migrateLegacyMixnode as migrateLegacyMixnodeReq,
migrateLegacyGateway as migrateLegacyGatewayReq,
bondNymNode,
updateNymNodeConfig as updateNymNodeConfigReq,
} from '../requests';
export type TBondedNode = TBondedMixnode | TBondedGateway | TBondedNymNode;
@@ -34,6 +35,10 @@ export type TBondingContext = {
unbond: (fee?: FeeDetails) => Promise<TransactionExecuteResult | undefined>;
bond: (args: TBondNymNodeArgs) => Promise<TransactionExecuteResult | undefined>;
updateBondAmount: (data: TUpdateBondArgs) => Promise<TransactionExecuteResult | undefined>;
updateNymNodeConfig: (data: {
host: string;
custom_http_port: number | null;
}) => Promise<TransactionExecuteResult | undefined>;
redeemRewards: (fee?: FeeDetails) => Promise<TransactionExecuteResult | undefined>;
generateNymNodeMsgPayload: (data: TNymNodeSignatureArgs) => Promise<string | undefined>;
migrateVestedMixnode: () => Promise<TransactionExecuteResult | undefined>;
@@ -52,6 +57,9 @@ export const BondingContext = createContext<TBondingContext>({
updateBondAmount: async () => {
throw new Error('Not implemented');
},
updateNymNodeConfig: async () => {
throw new Error('Not implemented');
},
redeemRewards: async () => {
throw new Error('Not implemented');
},
@@ -140,6 +148,23 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
return tx;
};
const updateNymNodeConfig = async (data: { host: string; custom_http_port: number | null }) => {
let tx;
setIsLoading(true);
try {
tx = await updateNymNodeConfigReq(data);
if (clientDetails?.client_address) {
await getNodeDetails(clientDetails?.client_address);
}
} catch (e) {
Console.warn(e);
setError(`an error occurred: ${e}`);
} finally {
setIsLoading(false);
}
return tx;
};
const redeemRewards = async (fee?: FeeDetails) => {
let tx;
setIsLoading(true);
@@ -225,6 +250,7 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
refresh,
redeemRewards,
updateBondAmount,
updateNymNodeConfig,
generateNymNodeMsgPayload,
migrateVestedMixnode,
migrateLegacyNode,
+9
View File
@@ -149,6 +149,14 @@ export const MockBondingContextProvider = ({
return TxResultMock;
};
const updateNymNodeConfig = async (): Promise<TransactionExecuteResult> => {
setIsLoading(true);
await mockSleep(SLEEP_MS);
triggerStateUpdate();
setIsLoading(false);
return TxResultMock;
};
const redeemRewards = async (): Promise<TransactionExecuteResult | undefined> => {
setIsLoading(true);
await mockSleep(SLEEP_MS);
@@ -212,6 +220,7 @@ export const MockBondingContextProvider = ({
isVestingAccount: false,
migrateVestedMixnode: async () => undefined,
migrateLegacyNode: async () => undefined,
updateNymNodeConfig,
}),
[isLoading, error, bondedMixnode, bondedGateway, trigger, fee],
);
@@ -3,22 +3,21 @@ import { useForm } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import { Box, Button, Divider, Grid, Stack, TextField, Typography } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { updateNymNodeConfig } from 'src/requests';
import { SimpleModal } from 'src/components/Modals/SimpleModal';
import { bondedInfoParametersValidationSchema } from 'src/components/Bonding/forms/legacyForms/mixnodeValidationSchema';
import { Console } from 'src/utils/console';
import { Alert } from 'src/components/Alert';
import { ConfirmTx } from 'src/components/ConfirmTX';
import { useGetFee } from 'src/hooks/useGetFee';
import { LoadingModal } from 'src/components/Modals/LoadingModal';
import { BalanceWarning } from 'src/components/FeeWarning';
import { AppContext } from 'src/context';
import { AppContext, useBondingContext } from 'src/context';
import { TBondedNymNode } from 'src/requests/nymNodeDetails';
import { settingsValidationSchema } from 'src/components/Bonding/forms/nym-node/settingsValidationSchema';
export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymNode }) => {
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
const { fee, resetFeeState } = useGetFee();
const { userBalance } = useContext(AppContext);
const { updateNymNodeConfig } = useBondingContext();
const theme = useTheme();
@@ -27,28 +26,26 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
handleSubmit,
formState: { errors, isSubmitting, isDirty, isValid },
} = useForm({
resolver: yupResolver(bondedInfoParametersValidationSchema),
resolver: yupResolver(settingsValidationSchema),
mode: 'onChange',
defaultValues: {
host: bondedNode.host,
customHttpPort: bondedNode.customHttpPort,
custom_http_port: bondedNode.customHttpPort,
},
});
const onSubmit = async (data: { host?: string; customHttpPort?: number | null }) => {
const onSubmit = async ({ host, custom_http_port }: { host: string; custom_http_port: number | null }) => {
resetFeeState();
const { host, customHttpPort } = data;
if (host && customHttpPort) {
try {
const NymNodeConfigParams = {
host,
custom_http_port: customHttpPort,
custom_http_port,
};
try {
await updateNymNodeConfig(NymNodeConfigParams);
setOpenConfirmationModal(true);
} catch (error) {
Console.error(error);
}
await updateNymNodeConfig(NymNodeConfigParams);
setOpenConfirmationModal(true);
} catch (error) {
Console.error(error);
}
};
@@ -59,7 +56,7 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
open
header="Update node settings"
fee={fee}
onConfirm={handleSubmit((d) => onSubmit(d))}
onConfirm={handleSubmit(onSubmit)}
onPrev={resetFeeState}
onClose={resetFeeState}
>
@@ -70,7 +67,6 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
)}
</ConfirmTx>
)}
{isSubmitting && <LoadingModal />}
<Alert
title={
<Stack>
@@ -93,12 +89,12 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
<Grid spacing={3} item container alignItems="center" xs={12} md={6}>
<Grid item width={1}>
<TextField
{...register('customHttpPort')}
name="customHttpPort"
{...register('custom_http_port')}
name="custom_http_port"
label="Custom HTTP port"
fullWidth
error={!!errors.customHttpPort}
helperText={errors.customHttpPort?.message}
error={!!errors.custom_http_port}
helperText={errors.custom_http_port?.message}
InputLabelProps={{ shrink: true }}
/>
</Grid>
@@ -134,7 +130,7 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
size="large"
variant="contained"
disabled={isSubmitting || !isDirty || !isValid}
onClick={handleSubmit(() => undefined)}
onClick={handleSubmit(onSubmit)}
sx={{ m: 3, mr: 0 }}
fullWidth
>
@@ -152,7 +148,7 @@ export const GeneralNymNodeSettings = ({ bondedNode }: { bondedNode: TBondedNymN
hideCloseIcon
displayInfoIcon
onOk={async () => {
await setOpenConfirmationModal(false);
setOpenConfirmationModal(false);
}}
buttonFullWidth
sx={{
+1 -1
View File
@@ -86,7 +86,7 @@ export type TNodeDescription = {
export type TNodeConfigUpdateArgs = {
host: string;
custom_http_port: number;
custom_http_port: number | null;
};
export type TDelegateArgs = {