dynamic values and remove hard coded code
This commit is contained in:
@@ -39,6 +39,12 @@ export type TBondedMixnode = {
|
||||
delegators: number;
|
||||
status: MixnodeStatus;
|
||||
proxy?: string;
|
||||
host: string;
|
||||
httpApiPort: number;
|
||||
mixPort: number;
|
||||
profitMarginPercent: number;
|
||||
verlocPort: number;
|
||||
version: string;
|
||||
};
|
||||
|
||||
export interface TBondedGateway {
|
||||
@@ -48,6 +54,12 @@ export interface TBondedGateway {
|
||||
bond: DecCoin;
|
||||
location?: string; // TODO not yet available, only available in Network Explorer API
|
||||
proxy?: string;
|
||||
host: string;
|
||||
httpApiPort: number;
|
||||
mixPort: number;
|
||||
profitMarginPercent: number;
|
||||
verlocPort: number;
|
||||
version: string;
|
||||
}
|
||||
|
||||
export type TokenPool = 'locked' | 'balance';
|
||||
@@ -165,6 +177,7 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod
|
||||
Console.warn(`get_operator_rewards request failed: ${e}`);
|
||||
}
|
||||
if (data) {
|
||||
const { mix_node } = data;
|
||||
const { status, stakeSaturation, numberOfDelegators } = await getAdditionalMixnodeDetails(
|
||||
data.mix_node.identity_key,
|
||||
);
|
||||
@@ -182,6 +195,12 @@ export const BondingContextProvider = ({ children }: { children?: React.ReactNod
|
||||
operatorRewards,
|
||||
status,
|
||||
stakeSaturation,
|
||||
host: mix_node.host,
|
||||
httpApiPort: mix_node.http_api_port,
|
||||
mixPort: mix_node.mix_port,
|
||||
profitMarginPercent: mix_node.profit_margin_percent,
|
||||
verlocPort: mix_node.verloc_port,
|
||||
version: mix_node.version,
|
||||
} as TBondedMixnode);
|
||||
}
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -16,6 +16,12 @@ const bondedMixnodeMock: TBondedMixnode = {
|
||||
operatorRewards: { denom: 'nym', amount: '1234' },
|
||||
delegators: 5423,
|
||||
status: 'active',
|
||||
host: '1.2.34.5 ',
|
||||
httpApiPort: 8000,
|
||||
mixPort: 1789,
|
||||
profitMarginPercent: 10,
|
||||
verlocPort: 1790,
|
||||
version: '1.0.2',
|
||||
};
|
||||
|
||||
const bondedGatewayMock: TBondedGateway = {
|
||||
@@ -23,6 +29,12 @@ const bondedGatewayMock: TBondedGateway = {
|
||||
identityKey: 'WayM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F',
|
||||
ip: '112.43.234.57',
|
||||
bond: { denom: 'nym', amount: '1234' },
|
||||
host: '1.2.34.5 ',
|
||||
httpApiPort: 8000,
|
||||
mixPort: 1789,
|
||||
profitMarginPercent: 10,
|
||||
verlocPort: 1790,
|
||||
version: '1.0.2',
|
||||
};
|
||||
|
||||
const TxResultMock: TransactionExecuteResult = {
|
||||
|
||||
@@ -16,23 +16,9 @@ import { isGateway, isMixnode, TBondGatewayArgs, TBondMixNodeArgs } from 'src/ty
|
||||
import { BondedGateway } from 'src/components/Bonding/BondedGateway';
|
||||
import { RedeemRewardsModal } from 'src/components/Bonding/modals/RedeemRewardsModal';
|
||||
import { CompoundRewardsModal } from 'src/components/Bonding/modals/CompoundRewardsModal';
|
||||
import { PageLayout } from '../../layouts';
|
||||
import { BondingContextProvider, useBondingContext, TBondedMixnode } from '../../context';
|
||||
import { BondingContextProvider, useBondingContext } from '../../context';
|
||||
import { Box } from '@mui/material';
|
||||
|
||||
// TODO: remove commented code to emulate a bonded mixnode
|
||||
const bondedMixnodeMock: TBondedMixnode = {
|
||||
name: 'Monster node',
|
||||
identityKey: '7mjM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F',
|
||||
stake: { denom: 'nym', amount: '1234' },
|
||||
bond: { denom: 'nym', amount: '1234' },
|
||||
stakeSaturation: 95,
|
||||
profitMargin: 15,
|
||||
operatorRewards: { denom: 'nym', amount: '1234' },
|
||||
delegators: 5423,
|
||||
status: 'active',
|
||||
};
|
||||
|
||||
const Bonding = () => {
|
||||
const [showModal, setShowModal] = useState<
|
||||
'bond-mixnode' | 'bond-gateway' | 'bond-more' | 'unbond' | 'redeem' | 'compound' | 'node-settings'
|
||||
@@ -164,11 +150,11 @@ const Bonding = () => {
|
||||
|
||||
return (
|
||||
<Box sx={{ mt: 4 }}>
|
||||
{!bondedMixnodeMock && <Bond disabled={isLoading} onBond={() => setShowModal('bond-mixnode')} />}
|
||||
{!bondedNode && <Bond disabled={isLoading} onBond={() => setShowModal('bond-mixnode')} />}
|
||||
|
||||
{bondedMixnodeMock && isMixnode(bondedMixnodeMock) && (
|
||||
{bondedNode && isMixnode(bondedNode) && (
|
||||
<BondedMixnode
|
||||
mixnode={bondedMixnodeMock}
|
||||
mixnode={bondedNode}
|
||||
network={network}
|
||||
onActionSelect={(action) => handleBondedMixnodeAction(action)}
|
||||
/>
|
||||
|
||||
@@ -1,52 +1,40 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Box, Button, Divider, Typography, TextField, Grid } from '@mui/material';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
|
||||
import { TBondedMixnode, TBondedGateway } from '../../../../context/bonding';
|
||||
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
|
||||
|
||||
type TSettingItem = {
|
||||
id: string;
|
||||
title: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
const portRegex = /^\d{4}$/;
|
||||
const ipRegex =
|
||||
/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
||||
// TODO: adding ip regex that works well
|
||||
const ipRegex = /^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$/;
|
||||
// TODO: only accept valid nym wallet versions
|
||||
const appVersionRegex = /^\d+(?:\.\d+){2}$/gm;
|
||||
|
||||
const currentMixPort: TSettingItem = { id: 'mixPort', title: 'Mix port', value: '1789' };
|
||||
const currentVerlocPort: TSettingItem = { id: 'verlocPort', title: 'Verloc Port', value: '1790' };
|
||||
const currentHttpPort: TSettingItem = { id: 'httpPort', title: 'HTTP Port', value: '8000' };
|
||||
const currentHost: TSettingItem = { id: 'host', title: 'Host', value: '95.216.92.229' };
|
||||
const currentVersion: TSettingItem = { id: 'version', title: 'Version', value: '1.0.8' };
|
||||
export const InfoSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const { mixPort, verlocPort, httpApiPort, host, version } = bondedNode;
|
||||
|
||||
export const InfoSettings = () => {
|
||||
const [valueChanged, setValueChanged] = useState<boolean>(false);
|
||||
const [buttonActive, setButtonActive] = useState<boolean>(false);
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
|
||||
const [mixPort, setMixPort] = useState<TSettingItem>(currentMixPort);
|
||||
const [verloc, setVerloc] = useState<TSettingItem>(currentVerlocPort);
|
||||
const [httpPort, setHttpPort] = useState<TSettingItem>(currentHttpPort);
|
||||
const [host, setHost] = useState<TSettingItem>(currentHost);
|
||||
const [version, setVersion] = useState<TSettingItem>(currentVersion);
|
||||
const [mixPortUpdated, setMixPortUpdated] = useState<number>(mixPort);
|
||||
const [verlocPortUpdated, setVerlocPortUpdated] = useState<number>(verlocPort);
|
||||
const [httpApiPortUpdated, setHttpApiPortUpdated] = useState<number>(httpApiPort);
|
||||
const [hostUpdated, setHostUpdated] = useState<string>(host);
|
||||
const [versionUpdated, setVersionUpdated] = useState<string>(version);
|
||||
|
||||
useEffect(() => {
|
||||
if (valueChanged) {
|
||||
if (
|
||||
Boolean(mixPort.value.match(portRegex)) &&
|
||||
Boolean(verloc.value.match(portRegex)) &&
|
||||
Boolean(httpPort.value.match(portRegex)) &&
|
||||
Boolean(host.value.match(ipRegex)) &&
|
||||
Boolean(version.value.match(appVersionRegex))
|
||||
Boolean(mixPortUpdated.toString().length === 4) &&
|
||||
Boolean(verlocPortUpdated.toString().length === 4) &&
|
||||
Boolean(httpApiPortUpdated.toString().length === 4) &&
|
||||
Boolean(versionUpdated.match(appVersionRegex))
|
||||
) {
|
||||
setButtonActive(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
setButtonActive(false);
|
||||
}, [valueChanged, mixPort, verloc, httpPort, host, version]);
|
||||
}, [valueChanged, mixPortUpdated, verlocPortUpdated, httpApiPortUpdated, hostUpdated, versionUpdated]);
|
||||
|
||||
return (
|
||||
<Box sx={{ width: '79.88%' }}>
|
||||
@@ -76,10 +64,10 @@ export const InfoSettings = () => {
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
type="input"
|
||||
label={mixPort.title}
|
||||
value={mixPort.value}
|
||||
label="Mix Port"
|
||||
value={mixPortUpdated}
|
||||
onChange={(e) => {
|
||||
setMixPort({ ...mixPort, value: e.target.value });
|
||||
setMixPortUpdated(parseInt(e.target.value));
|
||||
setValueChanged(true);
|
||||
}}
|
||||
fullWidth
|
||||
@@ -88,10 +76,10 @@ export const InfoSettings = () => {
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
type="input"
|
||||
label={verloc.title}
|
||||
value={verloc.value}
|
||||
label="Verloc Port"
|
||||
value={verlocPortUpdated}
|
||||
onChange={(e) => {
|
||||
setVerloc({ ...verloc, value: e.target.value });
|
||||
setVerlocPortUpdated(parseInt(e.target.value));
|
||||
setValueChanged(true);
|
||||
}}
|
||||
fullWidth
|
||||
@@ -100,10 +88,10 @@ export const InfoSettings = () => {
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
type="input"
|
||||
label={httpPort.title}
|
||||
value={httpPort.value}
|
||||
label="HTTP port"
|
||||
value={httpApiPortUpdated}
|
||||
onChange={(e) => {
|
||||
setHttpPort({ ...httpPort, value: e.target.value });
|
||||
setHttpApiPortUpdated(parseInt(e.target.value));
|
||||
setValueChanged(true);
|
||||
}}
|
||||
fullWidth
|
||||
@@ -128,10 +116,10 @@ export const InfoSettings = () => {
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
type="input"
|
||||
label={host.title}
|
||||
value={host.value}
|
||||
label="host"
|
||||
value={hostUpdated}
|
||||
onChange={(e) => {
|
||||
setHost({ ...host, value: e.target.value });
|
||||
setHostUpdated(e.target.value);
|
||||
setValueChanged(true);
|
||||
}}
|
||||
fullWidth
|
||||
@@ -156,10 +144,10 @@ export const InfoSettings = () => {
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
type="input"
|
||||
label={version.title}
|
||||
value={version.value}
|
||||
label="Version"
|
||||
value={versionUpdated}
|
||||
onChange={(e) => {
|
||||
setVersion({ ...version, value: e.target.value });
|
||||
setVersionUpdated(e.target.value);
|
||||
setValueChanged(true);
|
||||
}}
|
||||
fullWidth
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Box, Button, Divider, Typography, TextField, InputAdornment, Grid } from '@mui/material';
|
||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||
|
||||
import { TBondedMixnode, TBondedGateway } from '../../../../context/bonding';
|
||||
import { SimpleModal } from '../../../../components/Modals/SimpleModal';
|
||||
|
||||
type TSettingItem = {
|
||||
@@ -13,7 +13,7 @@ type TSettingItem = {
|
||||
const currentProfitMargin: TSettingItem = { id: 'profit-margin', title: 'Profit margin', value: 10 };
|
||||
const currentOperatorCost: TSettingItem = { id: 'operator-cost', title: 'Operator cost', value: 40 };
|
||||
|
||||
export const ParametersSettings = () => {
|
||||
export const ParametersSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const [buttonActive, setButtonActive] = useState<boolean>(false);
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
|
||||
const [profitMargin, setProfitMargin] = useState<TSettingItem>(currentProfitMargin);
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { Box, Button, Divider, Grid } from '@mui/material';
|
||||
import { TBondedMixnode, TBondedGateway } from '../../../../context/bonding';
|
||||
import { InfoSettings } from './InfoSettings';
|
||||
import { ParametersSettings } from './ParametersSettings';
|
||||
|
||||
const nodeGeneralNav = ['Info', 'Parameters'];
|
||||
|
||||
export const NodeGeneralSettings = () => {
|
||||
export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const [settingsCard, setSettingsCard] = useState<string>(nodeGeneralNav[0]);
|
||||
|
||||
console.log('node', bondedNode);
|
||||
return (
|
||||
<Box sx={{ pl: 3, pt: 3 }}>
|
||||
<Grid container direction="row" spacing={3}>
|
||||
@@ -32,8 +34,8 @@ export const NodeGeneralSettings = () => {
|
||||
))}
|
||||
</Grid>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
{settingsCard === nodeGeneralNav[0] && <InfoSettings />}
|
||||
{settingsCard === nodeGeneralNav[1] && <ParametersSettings />}
|
||||
{settingsCard === nodeGeneralNav[0] && <InfoSettings bondedNode={bondedNode} />}
|
||||
{settingsCard === nodeGeneralNav[1] && <ParametersSettings bondedNode={bondedNode} />}
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import React, { useContext, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { FeeDetails } from '@nymproject/types';
|
||||
import { Box, Typography, Stack, Toolbar, Button, Divider } from '@mui/material';
|
||||
@@ -7,7 +7,7 @@ import { ConfirmationDetailProps, ConfirmationDetailsModal } from 'src/component
|
||||
import { Node as NodeIcon } from 'src/svg-icons/node';
|
||||
import { NymCard } from '../../../components';
|
||||
import { PageLayout } from '../../../layouts';
|
||||
import { useBondingContext, TBondedMixnode } from '../../../context';
|
||||
import { useBondingContext, BondingContextProvider } from '../../../context';
|
||||
import { AppContext, urls } from 'src/context/main';
|
||||
|
||||
import { NodeGeneralSettings } from './general-settings';
|
||||
@@ -15,27 +15,11 @@ import { UnbondModal } from '../../../components/Bonding/modals/UnbondModal';
|
||||
|
||||
const nodeSettingsNav = ['General', 'Unbond'];
|
||||
|
||||
// TODO: remove commented code to emulate a bonded mixnode
|
||||
const bondedMixnodeMock: TBondedMixnode = {
|
||||
name: 'Monster node',
|
||||
identityKey: '7mjM2fYbtN6kxMwp1TrmQ4VwPks3URR5pBgWPWhzT98F',
|
||||
stake: { denom: 'nym', amount: '1234' },
|
||||
bond: { denom: 'nym', amount: '1234' },
|
||||
stakeSaturation: 95,
|
||||
profitMargin: 15,
|
||||
operatorRewards: { denom: 'nym', amount: '1234' },
|
||||
delegators: 5423,
|
||||
status: 'active',
|
||||
};
|
||||
|
||||
export const NodeSettingsPage = () => {
|
||||
export const NodeSettings = () => {
|
||||
const [settingsCard, setSettingsCard] = useState<string>(nodeSettingsNav[0]);
|
||||
const [confirmationDetails, setConfirmationDetails] = useState<ConfirmationDetailProps>();
|
||||
|
||||
const {
|
||||
network,
|
||||
userBalance: { originalVesting },
|
||||
} = useContext(AppContext);
|
||||
const { network } = useContext(AppContext);
|
||||
|
||||
const { bondedNode, unbond } = useBondingContext();
|
||||
|
||||
@@ -119,10 +103,10 @@ export const NodeSettingsPage = () => {
|
||||
}
|
||||
>
|
||||
<Divider />
|
||||
{settingsCard === nodeSettingsNav[0] && <NodeGeneralSettings />}
|
||||
{settingsCard === nodeSettingsNav[1] && bondedMixnodeMock && (
|
||||
{settingsCard === nodeSettingsNav[0] && bondedNode && <NodeGeneralSettings bondedNode={bondedNode} />}
|
||||
{settingsCard === nodeSettingsNav[1] && bondedNode && (
|
||||
<UnbondModal
|
||||
node={bondedMixnodeMock}
|
||||
node={bondedNode}
|
||||
onClose={() => setSettingsCard(nodeSettingsNav[0])}
|
||||
onConfirm={handleUnbond}
|
||||
onError={handleError}
|
||||
@@ -144,3 +128,9 @@ export const NodeSettingsPage = () => {
|
||||
</PageLayout>
|
||||
);
|
||||
};
|
||||
|
||||
export const NodeSettingsPage = () => (
|
||||
<BondingContextProvider>
|
||||
<NodeSettings />
|
||||
</BondingContextProvider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user