Gateway settings (#2725)
* add gateway settings button * remove unneeded mixnode type check * add additional properties to gateway type * update node settings nav options * set up gateway update requests * create gateway settings page * use update gateway validation * PR updates * dont show playground on gateways * set up gateway config update * fix lint errors in wallet * run cargo fmt
This commit is contained in:
@@ -119,6 +119,7 @@ fn main() {
|
||||
vesting::bond::vesting_unbond_mixnode,
|
||||
vesting::bond::vesting_update_mixnode_cost_params,
|
||||
vesting::bond::vesting_update_mixnode_config,
|
||||
vesting::bond::vesting_update_gateway_config,
|
||||
vesting::bond::withdraw_vested_coins,
|
||||
vesting::delegate::vesting_delegate_to_mixnode,
|
||||
vesting::delegate::vesting_undelegate_from_mixnode,
|
||||
@@ -154,6 +155,7 @@ fn main() {
|
||||
simulate::mixnet::simulate_unbond_mixnode,
|
||||
simulate::mixnet::simulate_update_mixnode_config,
|
||||
simulate::mixnet::simulate_update_mixnode_cost_params,
|
||||
simulate::mixnet::simulate_update_gateway_config,
|
||||
simulate::mixnet::simulate_delegate_to_mixnode,
|
||||
simulate::mixnet::simulate_undelegate_from_mixnode,
|
||||
simulate::vesting::simulate_vesting_delegate_to_mixnode,
|
||||
@@ -164,6 +166,7 @@ fn main() {
|
||||
simulate::vesting::simulate_vesting_pledge_more,
|
||||
simulate::vesting::simulate_vesting_unbond_mixnode,
|
||||
simulate::vesting::simulate_vesting_update_mixnode_config,
|
||||
simulate::vesting::simulate_vesting_update_gateway_config,
|
||||
simulate::vesting::simulate_vesting_update_mixnode_cost_params,
|
||||
simulate::vesting::simulate_withdraw_vested_coins,
|
||||
simulate::vesting::simulate_vesting_claim_delegator_reward,
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::error::BackendError;
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::WalletState;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::MixNodeConfigUpdate;
|
||||
use nym_mixnet_contract_common::{ExecuteMsg, Gateway, MixId, MixNode};
|
||||
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::mixnode::MixNodeCostParams;
|
||||
|
||||
@@ -130,6 +130,19 @@ pub async fn simulate_update_mixnode_config(
|
||||
.await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_update_gateway_config(
|
||||
update: GatewayConfigUpdate,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
simulate_mixnet_operation(
|
||||
ExecuteMsg::UpdateGatewayConfig { new_config: update },
|
||||
None,
|
||||
&state,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_delegate_to_mixnode(
|
||||
mix_id: MixId,
|
||||
|
||||
@@ -5,8 +5,8 @@ use crate::error::BackendError;
|
||||
use crate::operations::simulate::FeeDetails;
|
||||
use crate::WalletState;
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::MixNodeConfigUpdate;
|
||||
use nym_mixnet_contract_common::{Gateway, MixId, MixNode};
|
||||
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
|
||||
use nym_types::currency::DecCoin;
|
||||
use nym_types::mixnode::MixNodeCostParams;
|
||||
use nym_vesting_contract_common::ExecuteMsg;
|
||||
@@ -142,6 +142,19 @@ pub async fn simulate_vesting_update_mixnode_config(
|
||||
.await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_update_gateway_config(
|
||||
update: GatewayConfigUpdate,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<FeeDetails, BackendError> {
|
||||
simulate_vesting_operation(
|
||||
ExecuteMsg::UpdateGatewayConfig { new_config: update },
|
||||
None,
|
||||
&state,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn simulate_vesting_delegate_to_mixnode(
|
||||
mix_id: MixId,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::nyxd_client;
|
||||
use crate::state::WalletState;
|
||||
use crate::{Gateway, MixNode};
|
||||
use nym_contracts_common::signing::MessageSignature;
|
||||
use nym_mixnet_contract_common::MixNodeConfigUpdate;
|
||||
use nym_mixnet_contract_common::{GatewayConfigUpdate, MixNodeConfigUpdate};
|
||||
|
||||
use crate::operations::helpers::{
|
||||
verify_gateway_bonding_sign_payload, verify_mixnode_bonding_sign_payload,
|
||||
@@ -254,3 +254,28 @@ pub async fn vesting_update_mixnode_config(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn vesting_update_gateway_config(
|
||||
update: GatewayConfigUpdate,
|
||||
fee: Option<Fee>,
|
||||
state: tauri::State<'_, WalletState>,
|
||||
) -> Result<TransactionExecuteResult, BackendError> {
|
||||
let guard = state.read().await;
|
||||
let fee_amount = guard.convert_tx_fee(fee.as_ref());
|
||||
log::info!(
|
||||
">>> Update gateway config with locked tokens: update = {}, fee = {:?}",
|
||||
update.to_inline_json(),
|
||||
fee,
|
||||
);
|
||||
let res = guard
|
||||
.current_client()?
|
||||
.nyxd
|
||||
.vesting_update_gateway_config(update, fee)
|
||||
.await?;
|
||||
log::info!("<<< tx hash = {}", res.transaction_hash);
|
||||
log::trace!("<<< {:?}", res);
|
||||
Ok(TransactionExecuteResult::from_execute_result(
|
||||
res, fee_amount,
|
||||
)?)
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import React from 'react';
|
||||
import { Stack, Typography } from '@mui/material';
|
||||
import { Box, Button, Stack, Typography } from '@mui/material';
|
||||
import { Link } from '@nymproject/react/link/Link';
|
||||
import { TBondedGateway, urls } from 'src/context';
|
||||
import { NymCard } from 'src/components';
|
||||
import { Network } from 'src/types';
|
||||
import { IdentityKey } from 'src/components/IdentityKey';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Node as NodeIcon } from '../../svg-icons/node';
|
||||
import { Cell, Header, NodeTable } from './NodeTable';
|
||||
import { BondedGatewayActions, TBondedGatwayActions } from './BondedGatewayAction';
|
||||
|
||||
@@ -43,6 +45,7 @@ export const BondedGateway = ({
|
||||
onActionSelect: (action: TBondedGatwayActions) => void;
|
||||
}) => {
|
||||
const { name, bond, ip, identityKey, routingScore } = gateway;
|
||||
const navigate = useNavigate();
|
||||
const cells: Cell[] = [
|
||||
{
|
||||
cell: `${bond.amount} ${bond.denom}`,
|
||||
@@ -86,6 +89,18 @@ export const BondedGateway = ({
|
||||
<IdentityKey identityKey={identityKey} />
|
||||
</Stack>
|
||||
}
|
||||
Action={
|
||||
<Box>
|
||||
<Button
|
||||
variant="text"
|
||||
color="secondary"
|
||||
onClick={() => navigate('/bonding/node-settings')}
|
||||
startIcon={<NodeIcon />}
|
||||
>
|
||||
Gateway Settings
|
||||
</Button>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
<NodeTable headers={headers} cells={cells} />
|
||||
{network && (
|
||||
|
||||
@@ -66,3 +66,17 @@ export const amountSchema = Yup.object().shape({
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export const updateGatewayValidationSchema = Yup.object().shape({
|
||||
host: Yup.string()
|
||||
.required('A host is required')
|
||||
.test('valid-host', 'A valid host is required', (value) => (value ? isValidHostname(value) : false)),
|
||||
|
||||
mixPort: Yup.number()
|
||||
.required('A mixport is required')
|
||||
.test('valid-mixport', 'A valid mixport is required', (value) => (value ? validateRawPort(value) : false)),
|
||||
|
||||
httpApiPort: Yup.number()
|
||||
.required('A clients port is required')
|
||||
.test('valid-clients', 'A valid clients port is required', (value) => (value ? validateRawPort(value) : false)),
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import Big from 'big.js';
|
||||
import {
|
||||
EnumNodeType,
|
||||
isGateway,
|
||||
isMixnode,
|
||||
TBondGatewayArgs,
|
||||
@@ -93,7 +94,7 @@ export interface TBondedGateway {
|
||||
identityKey: string;
|
||||
ip: string;
|
||||
bond: DecCoin;
|
||||
location?: string; // TODO not yet available, only available in Network Explorer API
|
||||
location?: string;
|
||||
proxy?: string;
|
||||
host: string;
|
||||
httpApiPort: number;
|
||||
@@ -104,7 +105,6 @@ export interface TBondedGateway {
|
||||
current: number;
|
||||
average: number;
|
||||
};
|
||||
isUnbonding: boolean;
|
||||
}
|
||||
|
||||
export type TokenPool = 'locked' | 'balance';
|
||||
@@ -267,7 +267,7 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
const refresh = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
|
||||
if (ownership.hasOwnership && clientDetails) {
|
||||
if (ownership.hasOwnership && ownership.nodeType === EnumNodeType.mixnode && clientDetails) {
|
||||
try {
|
||||
const data = await getMixnodeBondDetails();
|
||||
let operatorRewards;
|
||||
@@ -330,21 +330,25 @@ export const BondingContextProvider: FCWithChildren = ({ children }): JSX.Elemen
|
||||
}
|
||||
}
|
||||
|
||||
if (ownership.hasOwnership) {
|
||||
if (ownership.hasOwnership && ownership.nodeType === EnumNodeType.gateway) {
|
||||
try {
|
||||
const data = await getGatewayBondDetails();
|
||||
if (data) {
|
||||
const { gateway, proxy } = data;
|
||||
const nodeDescription = await getNodeDescription(data.gateway.host, data.gateway.clients_port);
|
||||
const routingScore = await getGatewayReportDetails(data.gateway.identity_key);
|
||||
setBondedNode({
|
||||
name: nodeDescription?.name,
|
||||
identityKey: data.gateway.identity_key,
|
||||
ip: data.gateway.host,
|
||||
location: data.gateway.location,
|
||||
identityKey: gateway.identity_key,
|
||||
mixPort: gateway.mix_port,
|
||||
httpApiPort: gateway.clients_port,
|
||||
host: gateway.host,
|
||||
ip: gateway.host,
|
||||
location: gateway.location,
|
||||
bond: decCoinToDisplay(data.pledge_amount),
|
||||
proxy: data.proxy,
|
||||
proxy,
|
||||
routingScore,
|
||||
isUnbonding: false,
|
||||
version: gateway.version,
|
||||
} as TBondedGateway);
|
||||
}
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -47,7 +47,6 @@ const bondedGatewayMock: TBondedGateway = {
|
||||
average: 100,
|
||||
current: 100,
|
||||
},
|
||||
isUnbonding: false,
|
||||
};
|
||||
|
||||
const TxResultMock: TransactionExecuteResult = {
|
||||
|
||||
@@ -17,7 +17,7 @@ import { isMixnode } from 'src/types';
|
||||
import { getIntervalAsDate } from 'src/utils';
|
||||
import { NodeGeneralSettings } from './settings-pages/general-settings';
|
||||
import { NodeUnbondPage } from './settings-pages/NodeUnbondPage';
|
||||
import { createNavItems } from './node-settings.constant';
|
||||
import { makeNavItems } from './node-settings.constant';
|
||||
import { ApyPlayground } from './apy-playground';
|
||||
|
||||
export const NodeSettings = () => {
|
||||
@@ -87,7 +87,7 @@ export const NodeSettings = () => {
|
||||
</Box>
|
||||
<Box sx={{ width: '100%' }}>
|
||||
<Tabs
|
||||
tabs={createNavItems(isMixnode(bondedNode))}
|
||||
tabs={makeNavItems(isMixnode(bondedNode))}
|
||||
selectedTab={value}
|
||||
onChange={handleChange}
|
||||
tabSx={{
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export const createNavItems = (isMixnode: boolean) => {
|
||||
const navItems = ['Unbond'];
|
||||
if (isMixnode) return ['General', 'Playground', ...navItems];
|
||||
export const makeNavItems = (isMixnode: boolean) => {
|
||||
const navItems = ['General', 'Unbond'];
|
||||
|
||||
if (isMixnode) navItems.splice(1, 0, 'Playground');
|
||||
|
||||
return navItems;
|
||||
};
|
||||
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
import React, { useState } from 'react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { Button, Divider, Typography, TextField, Grid, Box } from '@mui/material';
|
||||
import { useTheme } from '@mui/material/styles';
|
||||
import {
|
||||
simulateUpdateGatewayConfig,
|
||||
simulateVestingUpdateGatewayConfig,
|
||||
updateGatewayConfig,
|
||||
vestingUpdateGatewayConfig,
|
||||
} from 'src/requests';
|
||||
import { TBondedGateway, useBondingContext } from 'src/context/bonding';
|
||||
import { SimpleModal } from 'src/components/Modals/SimpleModal';
|
||||
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 { updateGatewayValidationSchema } from 'src/components/Bonding/forms/gatewayValidationSchema';
|
||||
|
||||
export const GeneralGatewaySettings = ({ bondedNode }: { bondedNode: TBondedGateway }) => {
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
|
||||
const { getFee, fee, resetFeeState } = useGetFee();
|
||||
const { refresh } = useBondingContext();
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { errors, isSubmitting, isDirty, isValid },
|
||||
} = useForm({
|
||||
resolver: yupResolver(updateGatewayValidationSchema),
|
||||
mode: 'onChange',
|
||||
defaultValues: {
|
||||
host: bondedNode.host,
|
||||
mixPort: bondedNode.mixPort,
|
||||
httpApiPort: bondedNode.httpApiPort,
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (data: any) => {
|
||||
resetFeeState();
|
||||
const { host, mixPort, httpApiPort } = data;
|
||||
|
||||
try {
|
||||
const GatewayConfigParams = {
|
||||
host,
|
||||
mix_port: mixPort,
|
||||
clients_port: httpApiPort,
|
||||
location: bondedNode.location!,
|
||||
version: bondedNode.version,
|
||||
verloc_port: bondedNode.verlocPort,
|
||||
};
|
||||
|
||||
if (bondedNode.proxy) {
|
||||
await vestingUpdateGatewayConfig(GatewayConfigParams, fee?.fee);
|
||||
} else {
|
||||
await updateGatewayConfig(GatewayConfigParams, fee?.fee);
|
||||
}
|
||||
|
||||
setOpenConfirmationModal(true);
|
||||
} catch (error) {
|
||||
Console.error(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container xs item>
|
||||
{fee && (
|
||||
<ConfirmTx
|
||||
open
|
||||
header="Update node settings"
|
||||
fee={fee}
|
||||
onConfirm={handleSubmit((d) => onSubmit(d))}
|
||||
onPrev={resetFeeState}
|
||||
onClose={resetFeeState}
|
||||
/>
|
||||
)}
|
||||
{isSubmitting && <LoadingModal />}
|
||||
<Alert
|
||||
title={
|
||||
<Box sx={{ fontWeight: 600 }}>
|
||||
Changing these values will ONLY change the data about your node on the blockchain. Remember to change your
|
||||
node’s config file with the same values too
|
||||
</Box>
|
||||
}
|
||||
dismissable
|
||||
/>
|
||||
<Grid container>
|
||||
<Grid item container direction="row" alignItems="left" justifyContent="space-between" padding={3}>
|
||||
<Grid item>
|
||||
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1 }}>
|
||||
Port
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid spacing={3} item container alignItems="center" xs={12} md={6}>
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
{...register('mixPort')}
|
||||
name="mixPort"
|
||||
label="Mix Port"
|
||||
fullWidth
|
||||
error={!!errors.mixPort}
|
||||
helperText={errors.mixPort?.message}
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
{...register('httpApiPort')}
|
||||
name="httpApiPort"
|
||||
label="Client WS API Port"
|
||||
fullWidth
|
||||
error={!!errors.httpApiPort}
|
||||
helperText={errors.httpApiPort?.message}
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
<Grid item container direction="row" alignItems="left" justifyContent="space-between" padding={3}>
|
||||
<Grid item>
|
||||
<Typography variant="body1" sx={{ fontWeight: 600, mb: 1 }}>
|
||||
Host
|
||||
</Typography>
|
||||
</Grid>
|
||||
<Grid spacing={3} item container alignItems="center" xs={12} md={6}>
|
||||
<Grid item width={1}>
|
||||
<TextField
|
||||
{...register('host')}
|
||||
name="host"
|
||||
label="Host"
|
||||
fullWidth
|
||||
error={!!errors.host}
|
||||
helperText={errors.host?.message}
|
||||
InputLabelProps={{ shrink: true }}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Divider flexItem />
|
||||
<Grid container justifyContent="end">
|
||||
<Button
|
||||
size="large"
|
||||
variant="contained"
|
||||
disabled={isSubmitting || !isDirty || !isValid}
|
||||
onClick={handleSubmit((data) =>
|
||||
getFee(bondedNode.proxy ? simulateVestingUpdateGatewayConfig : simulateUpdateGatewayConfig, {
|
||||
host: data.host,
|
||||
mix_port: data.mixPort,
|
||||
clients_port: data.httpApiPort,
|
||||
location: bondedNode.location!,
|
||||
version: bondedNode.version,
|
||||
verloc_port: bondedNode.verlocPort,
|
||||
}),
|
||||
)}
|
||||
sx={{ m: 3 }}
|
||||
>
|
||||
Submit changes to the blockchain
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<SimpleModal
|
||||
open={openConfirmationModal}
|
||||
header="Your changes are submitted to the blockchain"
|
||||
subHeader="Remember to change the values
|
||||
on your gateways’s config file too."
|
||||
okLabel="close"
|
||||
hideCloseIcon
|
||||
displayInfoIcon
|
||||
onOk={async () => {
|
||||
setOpenConfirmationModal(false);
|
||||
await refresh();
|
||||
}}
|
||||
buttonFullWidth
|
||||
sx={{
|
||||
width: '450px',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
headerStyles={{
|
||||
width: '100%',
|
||||
mb: 1,
|
||||
textAlign: 'center',
|
||||
color: theme.palette.nym.nymWallet.text.blue,
|
||||
fontSize: 16,
|
||||
}}
|
||||
subHeaderStyles={{
|
||||
width: '100%',
|
||||
mb: 1,
|
||||
textAlign: 'center',
|
||||
color: 'main',
|
||||
fontSize: 14,
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
+2
-2
@@ -15,7 +15,7 @@ import { ConfirmTx } from 'src/components/ConfirmTX';
|
||||
import { useGetFee } from 'src/hooks/useGetFee';
|
||||
import { LoadingModal } from 'src/components/Modals/LoadingModal';
|
||||
|
||||
export const InfoSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
export const GeneralMixnodeSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const [openConfirmationModal, setOpenConfirmationModal] = useState<boolean>(false);
|
||||
const { getFee, fee, resetFeeState } = useGetFee();
|
||||
|
||||
@@ -141,7 +141,7 @@ export const InfoSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBon
|
||||
<TextField
|
||||
{...register('host')}
|
||||
name="host"
|
||||
label="host"
|
||||
label="Host"
|
||||
fullWidth
|
||||
error={!!errors.host}
|
||||
helperText={errors.host?.message}
|
||||
+35
-11
@@ -1,25 +1,50 @@
|
||||
import React, { useState } from 'react';
|
||||
import { Box, Button, Divider, Grid } from '@mui/material';
|
||||
import { isMixnode } from 'src/types';
|
||||
import { TBondedMixnode, TBondedGateway } from '../../../../../context/bonding';
|
||||
import { InfoSettings } from './InfoSettings';
|
||||
import { isGateway, isMixnode } from 'src/types';
|
||||
import { TBondedMixnode, TBondedGateway } from 'src/context/bonding';
|
||||
import { GeneralMixnodeSettings } from './GeneralMixnodeSettings';
|
||||
import { ParametersSettings } from './ParametersSettings';
|
||||
import { GeneralGatewaySettings } from './GeneralGatewaySettings';
|
||||
|
||||
const nodeGeneralNav = ['Node info', 'Parameters'];
|
||||
const makeGeneralNav = (bondedNode: TBondedMixnode | TBondedGateway) => {
|
||||
const navItems = ['Info'];
|
||||
if (isMixnode(bondedNode)) {
|
||||
navItems.push('Parameters');
|
||||
}
|
||||
|
||||
return navItems;
|
||||
};
|
||||
|
||||
export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode | TBondedGateway }) => {
|
||||
const [settingsCard, setSettingsCard] = useState<string>(nodeGeneralNav[0]);
|
||||
// TODO: Check what happens with a gateway
|
||||
const [navSelection, setNavSelection] = useState<number>(0);
|
||||
|
||||
const getSettings = () => {
|
||||
switch (navSelection) {
|
||||
case 0: {
|
||||
if (isMixnode(bondedNode)) return <GeneralMixnodeSettings bondedNode={bondedNode} />;
|
||||
if (isGateway(bondedNode)) return <GeneralGatewaySettings bondedNode={bondedNode} />;
|
||||
break;
|
||||
}
|
||||
case 1: {
|
||||
if (isMixnode(bondedNode)) return <ParametersSettings bondedNode={bondedNode} />;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ pl: 3, pt: 3 }}>
|
||||
<Grid container direction="row" spacing={3}>
|
||||
<Grid item container direction="column" xs={3}>
|
||||
{nodeGeneralNav.map((item) => (
|
||||
{makeGeneralNav(bondedNode).map((item, index) => (
|
||||
<Button
|
||||
size="small"
|
||||
sx={{
|
||||
fontSize: 14,
|
||||
color: settingsCard === item ? 'primary.main' : 'inherit',
|
||||
color: navSelection === index ? 'primary.main' : 'inherit',
|
||||
justifyContent: 'start',
|
||||
':hover': {
|
||||
bgcolor: 'transparent',
|
||||
@@ -27,15 +52,14 @@ export const NodeGeneralSettings = ({ bondedNode }: { bondedNode: TBondedMixnode
|
||||
},
|
||||
}}
|
||||
key={item}
|
||||
onClick={() => setSettingsCard(item)}
|
||||
onClick={() => setNavSelection(index)}
|
||||
>
|
||||
{item}
|
||||
</Button>
|
||||
))}
|
||||
</Grid>
|
||||
<Divider orientation="vertical" flexItem />
|
||||
{settingsCard === nodeGeneralNav[0] && <InfoSettings bondedNode={bondedNode} />}
|
||||
{settingsCard === nodeGeneralNav[1] && isMixnode(bondedNode) && <ParametersSettings bondedNode={bondedNode} />}
|
||||
{getSettings()}
|
||||
</Grid>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
TransactionExecuteResult,
|
||||
MixNodeConfigUpdate,
|
||||
MixNodeCostParams,
|
||||
GatewayConfigUpdate,
|
||||
} from '@nymproject/types';
|
||||
import {
|
||||
EnumNodeType,
|
||||
@@ -38,6 +39,9 @@ export const updateMixnodeCostParams = async (newCosts: MixNodeCostParams, fee?:
|
||||
export const updateMixnodeConfig = async (update: MixNodeConfigUpdate, fee?: Fee) =>
|
||||
invokeWrapper<TransactionExecuteResult>('update_mixnode_config', { update, fee });
|
||||
|
||||
export const updateGatewayConfig = async (update: GatewayConfigUpdate, fee?: Fee) =>
|
||||
invokeWrapper<TransactionExecuteResult>('update_gateway_config', { update, fee });
|
||||
|
||||
export const send = async (args: { amount: DecCoin; address: string; memo: string; fee?: Fee }) =>
|
||||
invokeWrapper<SendTxResult>('send', args);
|
||||
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
import { FeeDetails, DecCoin, Gateway, MixNodeCostParams, MixNodeConfigUpdate } from '@nymproject/types';
|
||||
import {
|
||||
FeeDetails,
|
||||
DecCoin,
|
||||
Gateway,
|
||||
MixNodeCostParams,
|
||||
MixNodeConfigUpdate,
|
||||
GatewayConfigUpdate,
|
||||
} from '@nymproject/types';
|
||||
import { TBondGatewayArgs, TBondMixNodeArgs } from 'src/types';
|
||||
import { invokeWrapper } from './wrapper';
|
||||
|
||||
@@ -18,6 +25,9 @@ export const simulateUpdateMixnodeCostParams = async (newCosts: MixNodeCostParam
|
||||
export const simulateUpdateMixnodeConfig = async (update: MixNodeConfigUpdate) =>
|
||||
invokeWrapper<FeeDetails>('simulate_update_mixnode_config', { update });
|
||||
|
||||
export const simulateUpdateGatewayConfig = async (update: GatewayConfigUpdate) =>
|
||||
invokeWrapper<FeeDetails>('simulate_update_gateway_config', { update });
|
||||
|
||||
export const simulateDelegateToMixnode = async (args: { mixId: number; amount: DecCoin }) =>
|
||||
invokeWrapper<FeeDetails>('simulate_delegate_to_mixnode', args);
|
||||
|
||||
@@ -53,6 +63,9 @@ export const simulateVestingUpdateMixnodeCostParams = async (newCosts: MixNodeCo
|
||||
export const simulateVestingUpdateMixnodeConfig = async (update: MixNodeConfigUpdate) =>
|
||||
invokeWrapper<FeeDetails>('simulate_vesting_update_mixnode_config', { update });
|
||||
|
||||
export const simulateVestingUpdateGatewayConfig = async (update: GatewayConfigUpdate) =>
|
||||
invokeWrapper<FeeDetails>('simulate_vesting_update_gateway_config', { update });
|
||||
|
||||
export const simulateWithdrawVestedCoins = async (args: any) =>
|
||||
invokeWrapper<FeeDetails>('simulate_withdraw_vested_coins', args);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
VestingAccountInfo,
|
||||
MixNodeCostParams,
|
||||
MixNodeConfigUpdate,
|
||||
GatewayConfigUpdate,
|
||||
} from '@nymproject/types';
|
||||
import { Fee } from '@nymproject/types/dist/types/rust/Fee';
|
||||
import { invokeWrapper } from './wrapper';
|
||||
@@ -80,6 +81,9 @@ export const vestingUpdateMixnodeCostParams = async (newCosts: MixNodeCostParams
|
||||
export const vestingUpdateMixnodeConfig = async (update: MixNodeConfigUpdate, fee?: Fee) =>
|
||||
invokeWrapper<TransactionExecuteResult>('vesting_update_mixnode_config', { update, fee });
|
||||
|
||||
export const vestingUpdateGatewayConfig = async (update: GatewayConfigUpdate, fee?: Fee) =>
|
||||
invokeWrapper<TransactionExecuteResult>('vesting_update_gateway_config', { update, fee });
|
||||
|
||||
export const vestingDelegateToMixnode = async (mixId: number, amount: DecCoin, fee?: Fee) =>
|
||||
invokeWrapper<TransactionExecuteResult>('vesting_delegate_to_mixnode', { mixId, amount, fee });
|
||||
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type Network = 'QA' | 'SANDBOX' | 'MAINNET';
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { DecCoin } from '@nymproject/types';
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DecCoin } from '@nymproject/types/src/types/rust/DecCoin';
|
||||
|
||||
export interface TauriContractStateParams {
|
||||
minimum_mixnode_pledge: DecCoin;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface ValidatorUrl {
|
||||
url: string;
|
||||
name: string | null;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { ValidatorUrl } from './ValidatorUrl';
|
||||
|
||||
export interface ValidatorUrls {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface GatewayCoreStatusResponse {
|
||||
identity: string;
|
||||
count: number;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface Interval {
|
||||
id: number;
|
||||
epochs_in_interval: number;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface IntervalRewardParams {
|
||||
reward_pool: string;
|
||||
staking_supply: string;
|
||||
staking_supply_scale_factor: string;
|
||||
epoch_reward_budget: string;
|
||||
stake_saturation_point: string;
|
||||
sybil_resistance: string;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface IntervalRewardingParamsUpdate {
|
||||
reward_pool: string | null;
|
||||
staking_supply: string | null;
|
||||
staking_supply_scale_factor: string | null;
|
||||
sybil_resistance_percent: string | null;
|
||||
active_set_work_factor: string | null;
|
||||
interval_pool_emission: string | null;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface MixNodeConfigUpdate {
|
||||
host: string;
|
||||
mix_port: number;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DecCoin } from './DecCoin';
|
||||
|
||||
export interface MixNodeCostParams {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { MixNodeBond } from './MixNodeBond';
|
||||
import type { MixNodeRewarding } from './MixNodeRewarding';
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { MixNodeCostParams } from './MixNodeCostParams';
|
||||
|
||||
export interface MixNodeRewarding {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface MixnodeCoreStatusResponse {
|
||||
mix_id: number;
|
||||
count: number;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PendingEpochEventData } from './PendingEpochEventData';
|
||||
|
||||
export interface PendingEpochEvent {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DecCoin } from './DecCoin';
|
||||
|
||||
export type PendingEpochEventData =
|
||||
| { Delegate: { owner: string; mix_id: number; amount: DecCoin; proxy: string | null } }
|
||||
| { Undelegate: { owner: string; mix_id: number; proxy: string | null } }
|
||||
| { PledgeMore: { mix_id: number; amount: DecCoin } }
|
||||
| { UnbondMixnode: { mix_id: number } }
|
||||
| { UpdateActiveSetSize: { new_size: number } };
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { PendingIntervalEventData } from './PendingIntervalEventData';
|
||||
|
||||
export interface PendingIntervalEvent {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { IntervalRewardingParamsUpdate } from './IntervalRewardingParamsUpdate';
|
||||
import type { MixNodeCostParams } from './MixNodeCostParams';
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface RewardEstimate {
|
||||
total_node_reward: string;
|
||||
operator: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { Interval } from './Interval';
|
||||
import type { RewardEstimate } from './RewardEstimate';
|
||||
import type { RewardingParams } from './RewardingParams';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { IntervalRewardParams } from './IntervalRewardParams';
|
||||
|
||||
export interface RewardingParams {
|
||||
|
||||
@@ -1 +1,3 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export type SelectionChance = 'High' | 'Good' | 'Low';
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
|
||||
export interface UnbondedMixnode {
|
||||
identity_key: string;
|
||||
owner: string;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
|
||||
import type { DelegationEvent } from './DelegationEvent';
|
||||
|
||||
export interface WrappedDelegationEvent {
|
||||
|
||||
@@ -19,6 +19,7 @@ export * from './Gas';
|
||||
export * from './GasInfo';
|
||||
export * from './Gateway';
|
||||
export * from './GatewayBond';
|
||||
export * from './GatewayConfigUpdate';
|
||||
export * from './GatewayCoreStatusResponse';
|
||||
export * from './InclusionProbabilityResponse';
|
||||
export * from './IntervalRewardingParamsUpdate';
|
||||
|
||||
Reference in New Issue
Block a user