diff --git a/nym-wallet/src/components/Bonding/modals/NodeCostParametersModals.tsx b/nym-wallet/src/components/Bonding/modals/NodeCostParametersModals.tsx
index a3b7aadf27..80c052ea3d 100644
--- a/nym-wallet/src/components/Bonding/modals/NodeCostParametersModals.tsx
+++ b/nym-wallet/src/components/Bonding/modals/NodeCostParametersModals.tsx
@@ -1,6 +1,6 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
-import { Typography } from '@mui/material';
+import { Typography, Box, Alert } from '@mui/material';
import { TBondedNode } from 'src/context';
import { useGetFee } from 'src/hooks/useGetFee';
import { ModalFee } from '../../Modals/ModalFee';
@@ -32,7 +32,9 @@ export const UpdateCostParametersModal = ({
}: Props) => {
const { fee, isFeeLoading, getFee, feeError } = useGetFee();
const [hasFetchedFee, setHasFetchedFee] = useState(false);
+ const [isSubmitting, setIsSubmitting] = useState(false);
+ // Handle fee errors
useEffect(() => {
if (feeError) {
onError(feeError);
@@ -50,7 +52,7 @@ export const UpdateCostParametersModal = ({
try {
const decimalProfitMargin = (parseFloat(profitMarginPercent) / 100).toString();
- const uNymAmount = String(Math.floor(Number(intervalOperatingCost) * 1000000));
+ const uNymAmount = String(Math.floor(Number(intervalOperatingCost || '0') * 1000000));
const costParams: NodeCostParams = {
profit_margin_percent: decimalProfitMargin,
@@ -61,7 +63,6 @@ export const UpdateCostParametersModal = ({
};
getFee(simulateUpdateMixnodeCostParams, costParams);
-
setHasFetchedFee(true);
} catch (error) {
onError(error as string);
@@ -69,18 +70,33 @@ export const UpdateCostParametersModal = ({
}
}, [hasFetchedFee, intervalOperatingCost, profitMarginPercent, getFee, onError, node]);
+ // Handle confirmation with loading state
+ const handleConfirm = async () => {
+ if (isSubmitting) return;
+
+ try {
+ setIsSubmitting(true);
+ await onConfirm();
+ } catch (error) {
+ onError(error as string);
+ } finally {
+ setIsSubmitting(false);
+ }
+ };
+
return (
+
These changes will affect your node's economics and delegator rewards.
Your new profit margin and operating cost will be applied in the next interval.
+
+ {/* Warning message */}
+
+
+
+ This action will overwrite your existing profit margin and operating cost settings.
+ Only one cost parameter update is allowed per epoch.
+
+
+
);
};
\ No newline at end of file
diff --git a/nym-wallet/src/components/Send/SendInputModal.tsx b/nym-wallet/src/components/Send/SendInputModal.tsx
index 0ac77f4b28..dc21ece24d 100644
--- a/nym-wallet/src/components/Send/SendInputModal.tsx
+++ b/nym-wallet/src/components/Send/SendInputModal.tsx
@@ -121,6 +121,19 @@ export const SendInputModal = ({
initialValue={amount?.amount}
denom={denom}
/>
+ onMemoChange(e.target.value)}
+ value={memo}
+ error={!memoIsValid}
+ placeholder="Optional"
+ helperText={
+ !memoIsValid ? 'The text is invalid, only alphanumeric characters and white spaces are allowed' : undefined
+ }
+ InputLabelProps={{ shrink: true }}
+ fullWidth
+ />
{error}
@@ -144,22 +157,8 @@ export const SendInputModal = ({
initialValue={userFees?.amount}
fullWidth
/>
- onMemoChange(e.target.value)}
- value={memo}
- error={!memoIsValid}
- helperText={
- !memoIsValid
- ? ' The text is invalid, only alphanumeric characters and white spaces are allowed'
- : undefined
- }
- InputLabelProps={{ shrink: true }}
- fullWidth
- />
)}
);
-};
+};
\ No newline at end of file
diff --git a/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeCostParameters.tsx b/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeCostParameters.tsx
index 3a2a0211f3..e8c8d4c717 100644
--- a/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeCostParameters.tsx
+++ b/nym-wallet/src/pages/bonding/node-settings/settings-pages/NodeCostParameters.tsx
@@ -11,9 +11,15 @@ interface Props {
bondedNode: TBondedNode;
onConfirm: () => Promise;
onError: (e: string) => void;
+ onUpdateData?: (profitMarginPercent: string, intervalOperatingCost: string, fee?: FeeDetails) => void;
}
-export const NodeCostParametersPage = ({ bondedNode, onConfirm, onError }: Props) => {
+export const NodeCostParametersPage = ({
+ bondedNode,
+ onConfirm,
+ onError,
+ onUpdateData
+}: Props) => {
const { updateCostParameters } = useBondingContext();
const [intervalOperatingCost, setIntervalOperatingCost] = useState('');
const [profitMarginPercent, setProfitMarginPercent] = useState('');
@@ -33,6 +39,12 @@ export const NodeCostParametersPage = ({ bondedNode, onConfirm, onError }: Props
}
}, [bondedNode]);
+ useEffect(() => {
+ if (onUpdateData && isFormValid) {
+ onUpdateData(profitMarginPercent, intervalOperatingCost, fee);
+ }
+ }, [profitMarginPercent, intervalOperatingCost, fee, isFormValid, onUpdateData]);
+
const handleIntervalOperatingCostChange = (e: React.ChangeEvent) => {
const value = e.target.value;
if (value === '' || /^[0-9]*\.?[0-9]*$/.test(value)) {
@@ -63,6 +75,10 @@ export const NodeCostParametersPage = ({ bondedNode, onConfirm, onError }: Props
try {
const uNymAmount = String(Math.floor(Number(intervalOperatingCost) * 1000000));
+ if (onUpdateData) {
+ onUpdateData(profitMarginPercent, intervalOperatingCost, fee);
+ }
+
await updateCostParameters(profitMarginPercent, uNymAmount, fee);
setIsConfirmed(false);
onConfirm();
@@ -120,7 +136,8 @@ export const NodeCostParametersPage = ({ bondedNode, onConfirm, onError }: Props
InputProps={{
endAdornment: %,
}}
- helperText="Input your profit margin (e.g., 20 for 20%)"
+ helperText="Input your profit margin (must be between 20% and 50%)"
+ error={profitMarginPercent !== '' && (Number(profitMarginPercent) < 20 || Number(profitMarginPercent) > 50)}
/>