Files
nym/wallet-web/pages/admin.tsx
Jędrzej Stuczyński 668325a4ce Feature/active sets (#764)
* 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>
2021-09-28 09:38:22 +01:00

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>
)
}