668325a4ce
* Added separate gateway active set size * Grabbing contract state * Defined PartialOrd on MixnodeBond and GatewayBond * Some initial stub for active set * Unit tests for mixnode and gateway bond partialord implementation * Obtaining active sets * Active nodes routes * Additional methods on validator client * Added state migration * Feature locking unused import * Fixed State test fixture * Included block height for partial_ord * Missing post-merge imports * api on the client for active nodes * Native/socks5/wasm clients using active nodes * Rewarding only active nodes * Updated validator client StateParams definition * Gateway active set size * Contract migration update * Cargo fmt * Updated TauriStateParams * [ci skip] Generate TS types Co-authored-by: jstuczyn <jstuczyn@users.noreply.github.com>
148 lines
5.4 KiB
TypeScript
148 lines
5.4 KiB
TypeScript
import { useRouter } from "next/router";
|
|
import React, { useContext, useEffect, useState } from "react";
|
|
import { ValidatorClientContext } from "../contexts/ValidatorClient";
|
|
import MainNav from "../components/MainNav";
|
|
import Paper from "@material-ui/core/Paper";
|
|
import Typography from "@material-ui/core/Typography";
|
|
import NoClientError from "../components/NoClientError";
|
|
import { makeStyles } from "@material-ui/core/styles";
|
|
import { ADMIN_ADDRESS } from "./_app";
|
|
import { LinearProgress } from "@material-ui/core";
|
|
import AdminForm from "../components/admin/AdminForm";
|
|
import { StateParams } from "@nymproject/nym-validator-client";
|
|
import { Alert, AlertTitle } from "@material-ui/lab";
|
|
import { printableBalanceToNative } from "@nymproject/nym-validator-client/dist/currency";
|
|
|
|
const useStyles = makeStyles((theme) => ({
|
|
appBar: {
|
|
position: 'relative',
|
|
},
|
|
layout: {
|
|
width: 'auto',
|
|
marginLeft: theme.spacing(2),
|
|
marginRight: theme.spacing(2),
|
|
[theme.breakpoints.up(600 + theme.spacing(2) * 2)]: {
|
|
width: 600,
|
|
marginLeft: 'auto',
|
|
marginRight: 'auto',
|
|
},
|
|
},
|
|
paper: {
|
|
marginTop: theme.spacing(3),
|
|
marginBottom: theme.spacing(3),
|
|
padding: theme.spacing(2),
|
|
[theme.breakpoints.up(600 + theme.spacing(3) * 2)]: {
|
|
marginTop: theme.spacing(6),
|
|
marginBottom: theme.spacing(6),
|
|
padding: theme.spacing(3),
|
|
},
|
|
},
|
|
buttons: {
|
|
display: 'flex',
|
|
justifyContent: 'flex-end',
|
|
},
|
|
button: {
|
|
marginTop: theme.spacing(3),
|
|
marginLeft: theme.spacing(1),
|
|
},
|
|
}));
|
|
|
|
export default function Admin() {
|
|
const classes = useStyles();
|
|
const router = useRouter()
|
|
|
|
const {client} = useContext(ValidatorClientContext)
|
|
|
|
const [currentStateParams, setCurrentStateParams] = useState(null)
|
|
const [updateError, setUpdateError] = useState(null)
|
|
const [updatingState, setUpdatingState] = useState(false)
|
|
|
|
// naive way of preventing non-tech-savvy people from accessing this page by manually changing
|
|
// page to /admin and thinking they're "l33t h4x0rs".
|
|
// However, even if somebody does access this page by telling the page their address is
|
|
// the same as that of the current admin,
|
|
// nothing is going to happen as they will be unable to sign a transaction to the contract without having
|
|
// access to the account itself
|
|
useEffect(() => {
|
|
(async () => {
|
|
if (client === null || client.address !== ADMIN_ADDRESS) {
|
|
await router.push("404")
|
|
} else {
|
|
let params = await client.getStateParams()
|
|
setCurrentStateParams(params)
|
|
}
|
|
})()
|
|
}, [client])
|
|
|
|
const updateStateParams = async (event) => {
|
|
event.preventDefault()
|
|
let newState: StateParams = {
|
|
minimum_mixnode_bond: printableBalanceToNative(event.target.mix_bond.value),
|
|
minimum_gateway_bond: printableBalanceToNative(event.target.gateway_bond.value),
|
|
mixnode_bond_reward_rate: event.target.mix_bond_reward.value,
|
|
gateway_bond_reward_rate: event.target.gateway_bond_reward.value,
|
|
mixnode_delegation_reward_rate: event.target.mix_delegation_reward.value,
|
|
gateway_delegation_reward_rate: event.target.gateway_delegation_reward.value,
|
|
epoch_length: parseInt(event.target.epoch_length.value),
|
|
mixnode_active_set_size: parseInt(event.target.mixnode_active_set.value),
|
|
gateway_active_set_size: parseInt(event.target.gateway_active_set.value),
|
|
};
|
|
setUpdatingState(true)
|
|
await client.updateStateParams(newState)
|
|
.then((_) => setCurrentStateParams(newState))
|
|
.catch((err) => setUpdateError(err))
|
|
.finally(() => setUpdatingState(false))
|
|
}
|
|
|
|
const getAdminContent = () => {
|
|
// we're not signed in (I guess it should get displayed super briefly before getting forwarded
|
|
// to a 404)
|
|
if (client === null) {
|
|
return (<NoClientError/>)
|
|
}
|
|
|
|
// we encountered error while trying to update state
|
|
if (updateError !== null) {
|
|
return (
|
|
<Alert severity="error">
|
|
<AlertTitle>{updateError.name}</AlertTitle>
|
|
<strong>Failed to update contract state</strong> - {updateError.message}
|
|
</Alert>
|
|
)
|
|
}
|
|
|
|
// We're getting current state params
|
|
if (currentStateParams === null) {
|
|
return (<LinearProgress/>)
|
|
}
|
|
|
|
if (updatingState) {
|
|
return (
|
|
<React.Fragment>
|
|
<br />
|
|
<Typography component="h1" variant="h5" align="center">
|
|
Updating contract state...
|
|
</Typography>
|
|
<LinearProgress/>
|
|
</React.Fragment>
|
|
)
|
|
}
|
|
|
|
return (<AdminForm onSubmit={updateStateParams} currentParams={currentStateParams}/>)
|
|
}
|
|
|
|
return (
|
|
<React.Fragment>
|
|
<MainNav/>
|
|
<main className={classes.layout}>
|
|
<Paper className={classes.paper}>
|
|
<Typography component="h1" variant="h4" align="center">
|
|
Contract control
|
|
</Typography>
|
|
|
|
{getAdminContent()}
|
|
</Paper>
|
|
</main>
|
|
</React.Fragment>
|
|
)
|
|
} |