prettier updates

This commit is contained in:
fmtabbara
2021-07-22 15:17:37 +01:00
parent ac4ee2bcf2
commit 70d4bce42f
6 changed files with 538 additions and 509 deletions
+30 -34
View File
@@ -1,16 +1,16 @@
import React from "react";
import Typography from "@material-ui/core/Typography";
import Grid from "@material-ui/core/Grid";
import { CircularProgress } from "@material-ui/core";
import { Alert, AlertTitle } from "@material-ui/lab";
import React from 'react'
import Typography from '@material-ui/core/Typography'
import Grid from '@material-ui/core/Grid'
import { CircularProgress } from '@material-ui/core'
import { Alert, AlertTitle } from '@material-ui/lab'
type ConfirmationProps = {
isLoading: boolean;
progressMessage: string;
successMessage: string;
failureMessage: string;
error: Error;
};
isLoading: boolean
progressMessage: string
successMessage: string
failureMessage: string
error: Error
}
export default function Confirmation({
isLoading,
@@ -19,29 +19,25 @@ export default function Confirmation({
failureMessage,
error,
}: ConfirmationProps) {
return (
<React.Fragment>
{isLoading ? (
<React.Fragment>
<Typography variant="h6" gutterBottom>
{progressMessage}
</Typography>
<Grid item xs={12} sm={6}>
<CircularProgress />
</Grid>
</React.Fragment>
return isLoading ? (
<>
<Typography variant='h6' gutterBottom>
{progressMessage}
</Typography>
<Grid item xs={12} sm={6}>
<CircularProgress />
</Grid>
</>
) : (
<>
{error === null ? (
<Alert severity='success'>{successMessage}</Alert>
) : (
<React.Fragment>
{error === null ? (
<Alert severity="success">{successMessage}</Alert>
) : (
<Alert severity="error">
<AlertTitle>{error.name}</AlertTitle>
<strong>{failureMessage}</strong> - {error.message}
</Alert>
)}
</React.Fragment>
<Alert severity='error'>
<AlertTitle>{error.name}</AlertTitle>
<strong>{failureMessage}</strong> - {error.message}
</Alert>
)}
</React.Fragment>
);
</>
)
}
+146 -146
View File
@@ -1,56 +1,56 @@
import React, { useEffect, useState, ChangeEvent } from "react";
import { printableBalanceToNative } from "@nymproject/nym-validator-client/dist/currency";
import { Coin, nativeToPrintable } from "@nymproject/nym-validator-client";
import { Alert } from "@material-ui/lab";
import Grid from "@material-ui/core/Grid";
import TextField from "@material-ui/core/TextField";
import React, { useEffect, useState, ChangeEvent } from 'react'
import { printableBalanceToNative } from '@nymproject/nym-validator-client/dist/currency'
import { Coin, nativeToPrintable } from '@nymproject/nym-validator-client'
import { Alert } from '@material-ui/lab'
import Grid from '@material-ui/core/Grid'
import TextField from '@material-ui/core/TextField'
import {
Button,
Checkbox,
FormControlLabel,
InputAdornment,
} from "@material-ui/core";
import bs58 from "bs58";
import semver from "semver";
import { NodeType } from "../../common/node";
import { theme } from "../../lib/theme";
} from '@material-ui/core'
import bs58 from 'bs58'
import semver from 'semver'
import { NodeType } from '../../common/node'
import { theme } from '../../lib/theme'
import {
basicRawCoinValueValidation,
makeBasicStyle,
validateRawPort,
} from "../../common/helpers";
import { DENOM } from "../../pages/_app";
import { BondingInformation } from "./NodeBond";
import { useGetBalance } from "../../hooks/useGetBalance";
} from '../../common/helpers'
import { DENOM } from '../../pages/_app'
import { BondingInformation } from './NodeBond'
import { useGetBalance } from '../../hooks/useGetBalance'
const DEFAULT_MIX_PORT = 1789;
const DEFAULT_VERLOC_PORT = 1790;
const DEFAULT_HTTP_API_PORT = 8000;
const DEFAULT_CLIENTS_PORT = 9000;
const DEFAULT_MIX_PORT = 1789
const DEFAULT_VERLOC_PORT = 1790
const DEFAULT_HTTP_API_PORT = 8000
const DEFAULT_CLIENTS_PORT = 9000
type TBondNodeFormProps = {
type: NodeType;
minimumMixnodeBond: Coin;
minimumGatewayBond: Coin;
onSubmit: (event: any) => void;
};
type: NodeType
minimumMixnodeBond: Coin
minimumGatewayBond: Coin
onSubmit: (event: any) => void
}
type TFormInput = {
amount: string;
host: string;
http_api_port: string;
mixPort: string;
verlocPort: string;
sphinxKey: string;
identityKey: string;
version: string;
location?: string;
clientsPort?: string;
httpApiPort?: string;
};
amount: string
host: string
http_api_port: string
mixPort: string
verlocPort: string
sphinxKey: string
identityKey: string
version: string
location?: string
clientsPort?: string
httpApiPort?: string
}
export default function BondNodeForm(props: TBondNodeFormProps) {
const classes = makeBasicStyle(theme);
const classes = makeBasicStyle(theme)
const [validity, setValidity] = React.useState({
validAmount: true,
@@ -69,19 +69,19 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
// gateway-specific:
validClientsPort: true,
});
})
const [advancedShown, setAdvancedShown] = React.useState(false);
const [allocationWarning, setAllocationWarning] = useState(false);
const { getBalance, accountBalance } = useGetBalance();
const [advancedShown, setAdvancedShown] = React.useState(false)
const [allocationWarning, setAllocationWarning] = useState(false)
const { getBalance, accountBalance } = useGetBalance()
useEffect(() => {
getBalance();
}, [getBalance]);
getBalance()
}, [getBalance])
const handleCheckboxToggle = () => {
setAdvancedShown((prevSet) => !prevSet);
};
setAdvancedShown((prevSet) => !prevSet)
}
const validateForm = ({
amount,
@@ -95,14 +95,14 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
httpApiPort,
clientsPort,
}: TFormInput): boolean => {
let validAmount = validateAmount(amount);
let validSphinxKey = validateKey(sphinxKey);
let validIdentityKey = validateKey(identityKey);
let validHost = validateHost(host);
let validVersion = validateVersion(version);
let validAmount = validateAmount(amount)
let validSphinxKey = validateKey(sphinxKey)
let validIdentityKey = validateKey(identityKey)
let validHost = validateHost(host)
let validVersion = validateVersion(version)
let validLocation =
props.type == NodeType.Gateway ? validateLocation(location) : true;
props.type == NodeType.Gateway ? validateLocation(location) : true
let newValidity = {
validAmount: validAmount,
@@ -111,16 +111,16 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
validHost: validHost,
validVersion: validVersion,
validLocation: validLocation,
};
}
if (advancedShown) {
let validMixPort = validateRawPort(mixPort);
let validMixPort = validateRawPort(mixPort)
let validVerlocPort =
props.type == NodeType.Mixnode ? validateRawPort(verlocPort) : true;
props.type == NodeType.Mixnode ? validateRawPort(verlocPort) : true
let validHttpApiPort =
props.type == NodeType.Mixnode ? validateRawPort(httpApiPort) : true;
props.type == NodeType.Mixnode ? validateRawPort(httpApiPort) : true
let validClientsPort =
props.type == NodeType.Gateway ? validateRawPort(clientsPort) : true;
props.type == NodeType.Gateway ? validateRawPort(clientsPort) : true
newValidity = {
...newValidity,
@@ -130,46 +130,46 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
validHttpApiPort: validHttpApiPort,
validClientsPort: validClientsPort,
},
};
}
}
setValidity((previousState) => {
return { ...previousState, ...newValidity };
});
return { ...previousState, ...newValidity }
})
// just AND everything together
const reducer = (acc, current) => acc && current;
const reducer = (acc, current) => acc && current
return Object.entries(newValidity)
.map((entry) => entry[1])
.reduce(reducer, true);
};
.reduce(reducer, true)
}
const validateAmount = (rawValue: string): boolean => {
// tests basic coin value requirements, like no more than 6 decimal places, value lower than total supply, etc
if (!basicRawCoinValueValidation(rawValue)) {
return false;
return false
}
// this conversion seems really iffy but I'm not sure how to better approach it
let nativeValueString = printableBalanceToNative(rawValue);
let nativeValue = parseInt(nativeValueString);
let nativeValueString = printableBalanceToNative(rawValue)
let nativeValue = parseInt(nativeValueString)
if (props.type == NodeType.Mixnode) {
return nativeValue >= parseInt(props.minimumMixnodeBond.amount);
return nativeValue >= parseInt(props.minimumMixnodeBond.amount)
} else {
return nativeValue >= parseInt(props.minimumGatewayBond.amount);
return nativeValue >= parseInt(props.minimumGatewayBond.amount)
}
};
}
const validateKey = (key: string): boolean => {
// it must be a valid base58 key
try {
const bytes = bs58.decode(key);
const bytes = bs58.decode(key)
// of length 32
return bytes.length === 32;
return bytes.length === 32
} catch {
return false;
return false
}
};
}
const validateHost = (host: string): boolean => {
// I don't think that proper checks are in scope of the change here
@@ -183,33 +183,33 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
// ipv6 can have multiple possible representations, but it needs to contain at least two colons
// a hostname (in this case) needs to have a top level domain present
const dot_occurrences = host.split(".").length - 1;
const colon_occurrences = host.split(":").length - 1;
const dot_occurrences = host.split('.').length - 1
const colon_occurrences = host.split(':').length - 1
if (dot_occurrences == 3) {
// possible ipv4
// make sure it has no ports attached!
return colon_occurrences == 0;
return colon_occurrences == 0
} else if (colon_occurrences >= 2) {
// possible ipv6
return true;
return true
} else if (dot_occurrences >= 1) {
// possible hostname
// make sure it has no ports attached!
return colon_occurrences == 0;
return colon_occurrences == 0
}
return false;
};
return false
}
const validateVersion = (version: string): boolean => {
// check if its a valid semver
return semver.valid(version) && semver.minor(version) >= 11;
};
return semver.valid(version) && semver.minor(version) >= 11
}
const validateLocation = (location: string): boolean => {
// right now only perform the stupid check of whether the user copy-pasted the tooltip... (with or without brackets)
return !location.trim().includes("physical location of your node");
};
return !location.trim().includes('physical location of your node')
}
const constructMixnodeBondingInfo = ({
amount,
@@ -234,8 +234,8 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
identity_key: identityKey,
version,
},
};
};
}
}
const constructGatewayBondingInfo = (
data: TFormInput
@@ -253,25 +253,25 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
version: data.version,
location: data.location,
},
};
};
}
}
const submitForm = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const target = event.target as unknown as TFormInput;
event.preventDefault()
const target = event.target as unknown as TFormInput
if (validateForm(target)) {
if (props.type == NodeType.Mixnode) {
return props.onSubmit(constructMixnodeBondingInfo(target));
return props.onSubmit(constructMixnodeBondingInfo(target))
} else {
return props.onSubmit(constructGatewayBondingInfo(target));
return props.onSubmit(constructGatewayBondingInfo(target))
}
}
};
}
let minimumBond = props.minimumMixnodeBond;
let minimumBond = props.minimumMixnodeBond
if (props.type == NodeType.Gateway) {
minimumBond = props.minimumGatewayBond;
minimumBond = props.minimumGatewayBond
}
// if this whole interface wasn't to be completely redone in a month time, I would have definitely redone the form
@@ -282,8 +282,8 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<Grid item xs={12} sm={8}>
<TextField
required
id="amount"
name="amount"
id='amount'
name='amount'
label={`Amount to bond (minimum ${nativeToPrintable(
minimumBond.amount
)} ${minimumBond.denom})`}
@@ -298,24 +298,24 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">{DENOM}</InputAdornment>
<InputAdornment position='end'>{DENOM}</InputAdornment>
),
}}
onChange={(e: ChangeEvent<HTMLInputElement>) => {
if (
typeof parseInt(e.target.value) === "number" &&
typeof parseInt(e.target.value) === 'number' &&
parseInt(accountBalance.amount) - parseInt(e.target.value) < 1
) {
setAllocationWarning(true);
setAllocationWarning(true)
} else {
setAllocationWarning(false);
setAllocationWarning(false)
}
}}
/>
</Grid>
{allocationWarning && (
<Grid item>
<Alert severity="info">
<Alert severity='info'>
You're about to allocate all of your tokens. You may want to keep
some in order to unbond this mixnode at a later time.
</Alert>
@@ -325,9 +325,9 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<TextField
error={!validity.validIdentityKey}
required
id="identity"
name="identity"
label="Identity key"
id='identity'
name='identity'
label='Identity key'
fullWidth
/>
</Grid>
@@ -335,12 +335,12 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<TextField
error={!validity.validSphinxKey}
required
id="sphinxKey"
name="sphinxKey"
label="Sphinx key"
id='sphinxKey'
name='sphinxKey'
label='Sphinx key'
fullWidth
{...(!validity.validSphinxKey
? { helperText: "Enter a valid sphinx key" }
? { helperText: 'Enter a valid sphinx key' }
: {})}
/>
</Grid>
@@ -348,12 +348,12 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<TextField
error={!validity.validHost}
required
id="host"
name="host"
label="Host"
id='host'
name='host'
label='Host'
fullWidth
{...(!validity.validHost
? { helperText: "Enter a valid IP or a hostname (without port)" }
? { helperText: 'Enter a valid IP or a hostname (without port)' }
: {})}
/>
</Grid>
@@ -364,12 +364,12 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<TextField
error={!validity.validLocation}
required
id="location"
name="location"
label="Location"
id='location'
name='location'
label='Location'
fullWidth
{...(!validity.validLocation
? { helperText: "Enter a valid location of your node" }
? { helperText: 'Enter a valid location of your node' }
: {})}
/>
)}
@@ -379,14 +379,14 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<TextField
error={!validity.validVersion}
required
id="version"
name="version"
label="Version"
id='version'
name='version'
label='Version'
fullWidth
{...(!validity.validVersion
? {
helperText:
"Enter a valid version (min. 0.11.0), like 0.11.0",
'Enter a valid version (min. 0.11.0), like 0.11.0',
}
: {})}
/>
@@ -400,37 +400,37 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
onChange={handleCheckboxToggle}
/>
}
label="Show advanced options"
label='Show advanced options'
/>
</Grid>
{advancedShown && (
<React.Fragment>
<>
<Grid item xs={12} sm={4}>
<TextField
error={!validity.validMixPort}
variant="outlined"
id="mixPort"
name="mixPort"
label="Mix Port"
variant='outlined'
id='mixPort'
name='mixPort'
label='Mix Port'
fullWidth
defaultValue={DEFAULT_MIX_PORT}
{...(!validity.validMixPort
? { helperText: "Enter a valid version, like 0.10.0" }
? { helperText: 'Enter a valid version, like 0.10.0' }
: {})}
/>
</Grid>
{/*yes, I also hate so many layers of indentation here*/}
{props.type === NodeType.Mixnode ? (
<React.Fragment>
<>
<Grid item xs={12} sm={4}>
<TextField
error={!validity.validVerlocPort}
variant="outlined"
id="verlocPort"
name="verlocPort"
label="Verloc Port"
variant='outlined'
id='verlocPort'
name='verlocPort'
label='Verloc Port'
fullWidth
defaultValue={DEFAULT_VERLOC_PORT}
/>
@@ -439,42 +439,42 @@ export default function BondNodeForm(props: TBondNodeFormProps) {
<Grid item xs={12} sm={4}>
<TextField
error={!validity.validHttpApiPort}
variant="outlined"
id="httpApiPort"
name="httpApiPort"
label="HTTP API Port"
variant='outlined'
id='httpApiPort'
name='httpApiPort'
label='HTTP API Port'
fullWidth
defaultValue={DEFAULT_HTTP_API_PORT}
/>
</Grid>
</React.Fragment>
</>
) : (
<Grid item xs={12} sm={4}>
<TextField
error={!validity.validClientsPort}
variant="outlined"
id="clientsPort"
name="clientsPort"
label="client WS API Port"
variant='outlined'
id='clientsPort'
name='clientsPort'
label='client WS API Port'
fullWidth
defaultValue={DEFAULT_CLIENTS_PORT}
/>
</Grid>
)}
</React.Fragment>
</>
)}
</Grid>
<div className={classes.buttons}>
<Button
variant="contained"
color="primary"
type="submit"
variant='contained'
color='primary'
type='submit'
className={classes.button}
>
Bond
</Button>
</div>
</form>
);
)
}
+162 -141
View File
@@ -1,163 +1,184 @@
import React, { useContext, useEffect } from 'react';
import Typography from '@material-ui/core/Typography';
import { Grid, LinearProgress, Paper } from '@material-ui/core';
import { Gateway, MixNode } from '@nymproject/nym-validator-client/dist/types';
import Confirmation from "../Confirmation";
import { ValidatorClientContext } from "../../contexts/ValidatorClient";
import NoClientError from "../NoClientError";
import { useRouter } from "next/router";
import BondNodeForm from "./BondNodeForm";
import { NodeType } from "../../common/node";
import Link from "../Link";
import { theme } from "../../lib/theme";
import { checkNodesOwnership, makeBasicStyle } from "../../common/helpers";
import NodeTypeChooser from "../NodeTypeChooser";
import ExecFeeNotice from "../ExecFeeNotice";
import { printableBalanceToNative } from "@nymproject/nym-validator-client/dist/currency";
import { coin } from "@nymproject/nym-validator-client";
import { UDENOM } from "../../pages/_app";
import React, { useContext, useEffect } from 'react'
import Typography from '@material-ui/core/Typography'
import { Grid, LinearProgress, Paper } from '@material-ui/core'
import { Gateway, MixNode } from '@nymproject/nym-validator-client/dist/types'
import Confirmation from '../Confirmation'
import { ValidatorClientContext } from '../../contexts/ValidatorClient'
import NoClientError from '../NoClientError'
import { useRouter } from 'next/router'
import BondNodeForm from './BondNodeForm'
import { NodeType } from '../../common/node'
import Link from '../Link'
import { theme } from '../../lib/theme'
import { checkNodesOwnership, makeBasicStyle } from '../../common/helpers'
import NodeTypeChooser from '../NodeTypeChooser'
import ExecFeeNotice from '../ExecFeeNotice'
import { printableBalanceToNative } from '@nymproject/nym-validator-client/dist/currency'
import { coin } from '@nymproject/nym-validator-client'
import { UDENOM } from '../../pages/_app'
export type BondingInformation = {
amount: string,
nodeDetails: MixNode | Gateway;
amount: string
nodeDetails: MixNode | Gateway
}
const BondNode = () => {
const classes = makeBasicStyle(theme);
const router = useRouter()
const {client} = useContext(ValidatorClientContext)
const classes = makeBasicStyle(theme)
const router = useRouter()
const { client } = useContext(ValidatorClientContext)
const [bondingStarted, setBondingStarted] = React.useState(false)
const [bondingFinished, setBondingFinished] = React.useState(false)
const [bondingError, setBondingError] = React.useState(null)
const [bondingStarted, setBondingStarted] = React.useState(false)
const [bondingFinished, setBondingFinished] = React.useState(false)
const [bondingError, setBondingError] = React.useState(null)
const [checkedOwnership, setCheckedOwnership] = React.useState(false)
const [ownsMixnode, setOwnsMixnode] = React.useState(false)
const [ownsGateway, setOwnsGateway] = React.useState(false)
const [checkedOwnership, setCheckedOwnership] = React.useState(false)
const [ownsMixnode, setOwnsMixnode] = React.useState(false)
const [ownsGateway, setOwnsGateway] = React.useState(false)
const [minimumMixnodeBond, setMinimumMixnodeBond] = React.useState(null)
const [minimumGatewayBond, setMinimumGatewayBond] = React.useState(null)
const [minimumMixnodeBond, setMinimumMixnodeBond] = React.useState(null)
const [minimumGatewayBond, setMinimumGatewayBond] = React.useState(null)
const [nodeType, setNodeType] = React.useState(NodeType.Mixnode)
const [nodeType, setNodeType] = React.useState(NodeType.Mixnode)
useEffect(() => {
const getInitialData = async () => {
if (client === null) {
await router.push("/")
} else {
const nodeOwnership = await checkNodesOwnership(client)
setOwnsMixnode(nodeOwnership.ownsMixnode)
setOwnsGateway(nodeOwnership.ownsGateway)
useEffect(() => {
const getInitialData = async () => {
if (client === null) {
await router.push('/')
} else {
const nodeOwnership = await checkNodesOwnership(client)
setOwnsMixnode(nodeOwnership.ownsMixnode)
setOwnsGateway(nodeOwnership.ownsGateway)
const minimumMixnodeBond = await client.minimumMixnodeBond()
setMinimumMixnodeBond(minimumMixnodeBond)
const minimumGatewayBond = await client.minimumGatewayBond()
setMinimumGatewayBond(minimumGatewayBond)
const minimumMixnodeBond = await client.minimumMixnodeBond()
setMinimumMixnodeBond(minimumMixnodeBond)
const minimumGatewayBond = await client.minimumGatewayBond()
setMinimumGatewayBond(minimumGatewayBond)
setCheckedOwnership(true)
}
}
getInitialData()
}, [client])
setCheckedOwnership(true)
}
}
getInitialData()
}, [client])
const bondNode = async (bondingInformation: BondingInformation) => {
setBondingStarted(true)
console.log(`BOND button pressed`);
const bondNode = async (bondingInformation: BondingInformation) => {
setBondingStarted(true)
console.log(`BOND button pressed`)
console.log(bondingInformation)
let amountValue = parseInt(printableBalanceToNative(bondingInformation.amount))
let amount = coin(amountValue, UDENOM)
console.log(bondingInformation)
let amountValue = parseInt(
printableBalanceToNative(bondingInformation.amount)
)
let amount = coin(amountValue, UDENOM)
console.log(bondingInformation.nodeDetails)
console.log(bondingInformation.nodeDetails)
if (nodeType == NodeType.Mixnode) {
let mixnode = (bondingInformation.nodeDetails as MixNode)
client.bondMixnode(mixnode, amount).then((value => {
console.log("bonded mixnode!", value)
})).catch(setBondingError).finally(() => setBondingFinished(true))
} else {
let gateway = (bondingInformation.nodeDetails as Gateway)
client.bondGateway(gateway, amount).then((value => {
console.log("bonded gateway!", value)
})).catch(setBondingError).finally(() => setBondingFinished(true))
}
if (nodeType == NodeType.Mixnode) {
let mixnode = bondingInformation.nodeDetails as MixNode
client
.bondMixnode(mixnode, amount)
.then((value) => {
console.log('bonded mixnode!', value)
})
.catch(setBondingError)
.finally(() => setBondingFinished(true))
} else {
let gateway = bondingInformation.nodeDetails as Gateway
client
.bondGateway(gateway, amount)
.then((value) => {
console.log('bonded gateway!', value)
})
.catch(setBondingError)
.finally(() => setBondingFinished(true))
}
}
const getBondContent = () => {
// we're not signed in
if (client === null) {
return <NoClientError />
}
const getBondContent = () => {
// we're not signed in
if (client === null) {
return (<NoClientError/>)
}
// we haven't checked whether we actually already own a node
if (!checkedOwnership) {
return (<LinearProgress/>)
}
// we already own a mixnode
if (ownsMixnode) {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography gutterBottom>
You have already have a bonded mixnode. If you wish to bond a different one, you need to
first <Link href="/unbond">unbond the existing one</Link>.
</Typography>
</Grid>
</Grid>
)
}
// we already own a gateway
if (ownsGateway) {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography gutterBottom>
You have already have a bonded gateway. If you wish to bond a different one, you need to
first <Link href="/unbond">unbond the existing one</Link>.
</Typography>
</Grid>
</Grid>
)
}
// we haven't clicked bond button yet
if (!bondingStarted) {
return (
<React.Fragment>
<NodeTypeChooser nodeType={nodeType} setNodeType={setNodeType}/>
<BondNodeForm onSubmit={bondNode} type={nodeType} minimumGatewayBond={minimumGatewayBond}
minimumMixnodeBond={minimumMixnodeBond}/>
</React.Fragment>
)
}
// We started bonding
return (
<Confirmation
finished={bondingFinished}
error={bondingError}
progressMessage={`${nodeType} bonding is in progress...`}
successMessage={`${nodeType} bonding was successful!`}
failureMessage={`Failed to bond the ${nodeType}!`}
/>
)
// we haven't checked whether we actually already own a node
if (!checkedOwnership) {
return <LinearProgress />
}
// we already own a mixnode
if (ownsMixnode) {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography gutterBottom>
You have already have a bonded mixnode. If you wish to bond a
different one, you need to first{' '}
<Link href='/unbond'>unbond the existing one</Link>.
</Typography>
</Grid>
</Grid>
)
}
// we already own a gateway
if (ownsGateway) {
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Typography gutterBottom>
You have already have a bonded gateway. If you wish to bond a
different one, you need to first{' '}
<Link href='/unbond'>unbond the existing one</Link>.
</Typography>
</Grid>
</Grid>
)
}
// we haven't clicked bond button yet
if (!bondingStarted) {
return (
<>
<NodeTypeChooser nodeType={nodeType} setNodeType={setNodeType} />
<BondNodeForm
onSubmit={bondNode}
type={nodeType}
minimumGatewayBond={minimumGatewayBond}
minimumMixnodeBond={minimumMixnodeBond}
/>
</>
)
}
// We started bonding
return (
<React.Fragment>
<main className={classes.layout}>
<Paper className={classes.paper}>
<ExecFeeNotice name="bonding"/>
<Typography component="h1" variant="h4" align="center" className={classes.wrapper}>
Bond a {nodeType}
</Typography>
{getBondContent()}
</Paper>
</main>
</React.Fragment>
);
};
<Confirmation
isLoading={bondingFinished}
error={bondingError}
progressMessage={`${nodeType} bonding is in progress...`}
successMessage={`${nodeType} bonding was successful!`}
failureMessage={`Failed to bond the ${nodeType}!`}
/>
)
}
export default BondNode;
return (
<>
<main className={classes.layout}>
<Paper className={classes.paper}>
<ExecFeeNotice name='bonding' />
<Typography
component='h1'
variant='h4'
align='center'
className={classes.wrapper}
>
Bond a {nodeType}
</Typography>
{getBondContent()}
</Paper>
</main>
</>
)
}
export default BondNode
+49 -49
View File
@@ -1,32 +1,32 @@
import React, { useState, useEffect, ChangeEvent } from "react";
import Grid from "@material-ui/core/Grid";
import { Button, InputAdornment } from "@material-ui/core";
import TextField from "@material-ui/core/TextField";
import { DENOM } from "../../pages/_app";
import { theme } from "../../lib/theme";
import React, { useState, useEffect } from 'react'
import Grid from '@material-ui/core/Grid'
import { Button, InputAdornment } from '@material-ui/core'
import TextField from '@material-ui/core/TextField'
import { Alert } from '@material-ui/lab'
import { DENOM } from '../../pages/_app'
import { theme } from '../../lib/theme'
import {
basicRawCoinValueValidation,
makeBasicStyle,
validateIdentityKey,
} from "../../common/helpers";
import { useGetBalance } from "../../hooks/useGetBalance";
import { Alert } from "@material-ui/lab";
} from '../../common/helpers'
import { useGetBalance } from '../../hooks/useGetBalance'
type DelegateFormProps = {
onSubmit: (event: any) => void;
};
onSubmit: (event: any) => void
}
export default function DelegateForm(props: DelegateFormProps) {
const classes = makeBasicStyle(theme);
const classes = makeBasicStyle(theme)
const [validAmount, setValidAmount] = useState(true);
const [validIdentity, setValidIdentity] = useState(true);
const [allocationWarning, setAllocationWarning] = useState(false);
const { getBalance, accountBalance } = useGetBalance();
const [validAmount, setValidAmount] = useState(true)
const [validIdentity, setValidIdentity] = useState(true)
const [allocationWarning, setAllocationWarning] = useState(false)
const { getBalance, accountBalance } = useGetBalance()
useEffect(() => {
getBalance();
}, [getBalance]);
getBalance()
}, [getBalance])
// const [checkboxSet, setCheckboxSet] = React.useState(false)
@@ -38,40 +38,40 @@ export default function DelegateForm(props: DelegateFormProps) {
// don't ask me about that. javascript works in mysterious ways
// and this is apparently a good way of checking if string
// is purely made of numeric characters
let parsed = +event.target.value;
let parsed = +event.target.value
if (isNaN(parsed)) {
setValidAmount(false);
setValidAmount(false)
} else {
if (parsed > 0 && parseInt(accountBalance.amount) - parsed < 1) {
setAllocationWarning(true);
setAllocationWarning(true)
} else {
setAllocationWarning(false);
setAllocationWarning(false)
}
setValidAmount(true);
setValidAmount(true)
}
};
}
const validateForm = (event: any): boolean => {
let validIdentity = validateIdentityKey(event.target.identity.value);
let validAmount = validateAmount(event.target.amount.value);
let validIdentity = validateIdentityKey(event.target.identity.value)
let validAmount = validateAmount(event.target.amount.value)
setValidIdentity(validIdentity);
setValidAmount(validAmount);
setValidIdentity(validIdentity)
setValidAmount(validAmount)
return validIdentity && validAmount;
};
return validIdentity && validAmount
}
const validateAmount = (rawAmount: string): boolean => {
return basicRawCoinValueValidation(rawAmount);
};
return basicRawCoinValueValidation(rawAmount)
}
const submitForm = (event: any) => {
event.preventDefault();
event.preventDefault()
if (validateForm(event)) {
return props.onSubmit(event);
return props.onSubmit(event)
}
};
}
return (
<form onSubmit={submitForm}>
@@ -79,13 +79,13 @@ export default function DelegateForm(props: DelegateFormProps) {
<Grid item xs={12}>
<TextField
required
id="identity"
name="identity"
label="Node identity"
id='identity'
name='identity'
label='Node identity'
error={!validIdentity}
helperText={
validIdentity
? ""
? ''
: "Please enter a valid identity like '824WyExLUWvLE2mpSHBatN4AoByuLzfnHFeHWiBYzg4z'"
}
fullWidth
@@ -95,23 +95,23 @@ export default function DelegateForm(props: DelegateFormProps) {
<Grid item xs={12} sm={6}>
<TextField
required
id="amount"
name="amount"
label="Amount to delegate"
id='amount'
name='amount'
label='Amount to delegate'
error={!validAmount}
helperText={validAmount ? "" : "Please enter a valid amount"}
helperText={validAmount ? '' : 'Please enter a valid amount'}
onChange={handleAmountChange}
fullWidth
InputProps={{
endAdornment: (
<InputAdornment position="end">{DENOM}</InputAdornment>
<InputAdornment position='end'>{DENOM}</InputAdornment>
),
}}
/>
</Grid>
{allocationWarning && (
<Grid item>
<Alert severity="info">
<Alert severity='info'>
You're about to allocate all of your tokens. You may want to keep
some in order to unbond this mixnode at a later time.
</Alert>
@@ -133,14 +133,14 @@ export default function DelegateForm(props: DelegateFormProps) {
</Grid>
<div className={classes.buttons}>
<Button
variant="contained"
color="primary"
type="submit"
variant='contained'
color='primary'
type='submit'
className={classes.button}
>
Delegate stake
</Button>
</div>
</form>
);
)
}
+111 -99
View File
@@ -1,112 +1,124 @@
import React, { useContext, useEffect } from "react";
import { Paper } from "@material-ui/core";
import Typography from "@material-ui/core/Typography";
import { useRouter } from "next/router";
import { ValidatorClientContext } from "../../contexts/ValidatorClient";
import { NodeType } from "../../common/node";
import NoClientError from "../NoClientError";
import Confirmation from "../Confirmation";
import DelegateForm from "./DelegateForm";
import { printableBalanceToNative } from "@nymproject/nym-validator-client/dist/currency";
import { Coin } from "@cosmjs/launchpad";
import { coin, printableCoin } from "@nymproject/nym-validator-client";
import { UDENOM } from "../../pages/_app";
import { theme } from "../../lib/theme";
import { makeBasicStyle } from "../../common/helpers";
import NodeTypeChooser from "../NodeTypeChooser";
import ExecFeeNotice from "../ExecFeeNotice";
import React, { useContext, useEffect } from 'react'
import { Paper } from '@material-ui/core'
import Typography from '@material-ui/core/Typography'
import { useRouter } from 'next/router'
import { ValidatorClientContext } from '../../contexts/ValidatorClient'
import { NodeType } from '../../common/node'
import NoClientError from '../NoClientError'
import Confirmation from '../Confirmation'
import DelegateForm from './DelegateForm'
import { printableBalanceToNative } from '@nymproject/nym-validator-client/dist/currency'
import { Coin } from '@cosmjs/launchpad'
import { coin, printableCoin } from '@nymproject/nym-validator-client'
import { UDENOM } from '../../pages/_app'
import { theme } from '../../lib/theme'
import { makeBasicStyle } from '../../common/helpers'
import NodeTypeChooser from '../NodeTypeChooser'
import ExecFeeNotice from '../ExecFeeNotice'
const DelegateToNode = () => {
const classes = makeBasicStyle(theme);
const router = useRouter()
const {client} = useContext(ValidatorClientContext)
const classes = makeBasicStyle(theme)
const router = useRouter()
const { client } = useContext(ValidatorClientContext)
const [delegationStarted, setDelegationStarted] = React.useState(false)
const [delegationFinished, setDelegationFinished] = React.useState(false)
const [delegationError, setDelegationError] = React.useState(null)
const [delegationStarted, setDelegationStarted] = React.useState(false)
const [delegationFinished, setDelegationFinished] = React.useState(false)
const [delegationError, setDelegationError] = React.useState(null)
const [nodeType, setNodeType] = React.useState(NodeType.Mixnode)
const [stakeValue, setStakeValue] = React.useState("0 HAL")
const [nodeIdentity, setNodeIdentity] = React.useState("")
const [nodeType, setNodeType] = React.useState(NodeType.Mixnode)
const [stakeValue, setStakeValue] = React.useState('0 HAL')
const [nodeIdentity, setNodeIdentity] = React.useState('')
useEffect(() => {
const checkClient = async () => {
if (client === null) {
await router.push("/")
}
}
checkClient()
}, [client])
useEffect(() => {
const checkClient = async () => {
if (client === null) {
await router.push('/')
}
}
checkClient()
}, [client])
const getDelegationValue = (raw: string): Coin => {
let native = printableBalanceToNative(raw)
return coin(parseInt(native), UDENOM)
const getDelegationValue = (raw: string): Coin => {
let native = printableBalanceToNative(raw)
return coin(parseInt(native), UDENOM)
}
const delegateToNode = async (event) => {
event.preventDefault()
console.log(`DELEGATE button pressed`)
const nodeIdentity = event.target.identity.value
const delegationValue = getDelegationValue(event.target.amount.value)
setNodeIdentity(nodeIdentity)
setStakeValue(printableCoin(delegationValue))
setDelegationStarted(true)
if (nodeType == NodeType.Mixnode) {
client
.delegateToMixnode(nodeIdentity, delegationValue)
.then((value) => {
console.log('delegated to mixnode!', value)
})
.catch(setDelegationError)
.finally(() => setDelegationFinished(true))
} else {
client
.delegateToGateway(nodeIdentity, delegationValue)
.then((value) => {
console.log('delegated to gateway!', value)
})
.catch(setDelegationError)
.finally(() => setDelegationFinished(true))
}
}
const getDelegationContent = () => {
// we're not signed in
if (client === null) {
return <NoClientError />
}
const delegateToNode = async (event) => {
event.preventDefault();
console.log(`DELEGATE button pressed`);
const nodeIdentity = event.target.identity.value;
const delegationValue = getDelegationValue(event.target.amount.value)
setNodeIdentity(nodeIdentity)
setStakeValue(printableCoin(delegationValue))
setDelegationStarted(true)
if (nodeType == NodeType.Mixnode) {
client.delegateToMixnode(nodeIdentity, delegationValue).then((value => {
console.log("delegated to mixnode!", value)
})).catch(setDelegationError).finally(() => setDelegationFinished(true))
} else {
client.delegateToGateway(nodeIdentity, delegationValue).then((value => {
console.log("delegated to gateway!", value)
})).catch(setDelegationError).finally(() => setDelegationFinished(true))
}
}
const getDelegationContent = () => {
// we're not signed in
if (client === null) {
return (<NoClientError/>)
}
// we haven't clicked delegate button yet
if (!delegationStarted) {
return (
<React.Fragment>
<NodeTypeChooser nodeType={nodeType} setNodeType={setNodeType}/>
<DelegateForm onSubmit={delegateToNode}/>
</React.Fragment>
)
}
// We started delegation
return (
<Confirmation
finished={delegationFinished}
error={delegationError}
progressMessage={`Delegating stake on ${nodeType} ${nodeIdentity} is in progress...`}
successMessage={`Successfully delegated ${stakeValue} stake on ${nodeType} ${nodeIdentity}`}
failureMessage={`Failed to delegate to a ${nodeType}!`}
/>
)
// we haven't clicked delegate button yet
if (!delegationStarted) {
return (
<>
<NodeTypeChooser nodeType={nodeType} setNodeType={setNodeType} />
<DelegateForm onSubmit={delegateToNode} />
</>
)
}
// We started delegation
return (
<React.Fragment>
<main className={classes.layout}>
<Paper className={classes.paper}>
<ExecFeeNotice name={"delegating stake"}/>
<Typography component="h1" variant="h4" align="center" className={classes.wrapper}>
Delegate to {nodeType}
</Typography>
{getDelegationContent()}
</Paper>
</main>
</React.Fragment>
);
<Confirmation
finished={delegationFinished}
error={delegationError}
progressMessage={`Delegating stake on ${nodeType} ${nodeIdentity} is in progress...`}
successMessage={`Successfully delegated ${stakeValue} stake on ${nodeType} ${nodeIdentity}`}
failureMessage={`Failed to delegate to a ${nodeType}!`}
/>
)
}
return (
<>
<main className={classes.layout}>
<Paper className={classes.paper}>
<ExecFeeNotice name={'delegating stake'} />
<Typography
component='h1'
variant='h4'
align='center'
className={classes.wrapper}
>
Delegate to {nodeType}
</Typography>
{getDelegationContent()}
</Paper>
</main>
</>
)
}
export default DelegateToNode;
export default DelegateToNode
+40 -40
View File
@@ -1,28 +1,28 @@
import React, { useContext, useEffect } from "react";
import Paper from "@material-ui/core/Paper";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import RefreshIcon from "@material-ui/icons/Refresh";
import { makeStyles } from "@material-ui/core/styles";
import { useRouter } from "next/router";
import { ValidatorClientContext } from "../contexts/ValidatorClient";
import MainNav from "../components/MainNav";
import Confirmation from "../components/Confirmation";
import NoClientError from "../components/NoClientError";
import { useGetBalance } from "../hooks/useGetBalance";
import React, { useContext, useEffect } from 'react'
import Paper from '@material-ui/core/Paper'
import Typography from '@material-ui/core/Typography'
import Button from '@material-ui/core/Button'
import RefreshIcon from '@material-ui/icons/Refresh'
import { makeStyles } from '@material-ui/core/styles'
import { useRouter } from 'next/router'
import { ValidatorClientContext } from '../contexts/ValidatorClient'
import MainNav from '../components/MainNav'
import Confirmation from '../components/Confirmation'
import NoClientError from '../components/NoClientError'
import { useGetBalance } from '../hooks/useGetBalance'
const useStyles = makeStyles((theme) => ({
appBar: {
position: "relative",
position: 'relative',
},
layout: {
width: "auto",
width: 'auto',
marginLeft: theme.spacing(2),
marginRight: theme.spacing(2),
[theme.breakpoints.up(600 + theme.spacing(2) * 2)]: {
width: 600,
marginLeft: "auto",
marginRight: "auto",
marginLeft: 'auto',
marginRight: 'auto',
},
},
paper: {
@@ -36,61 +36,61 @@ const useStyles = makeStyles((theme) => ({
},
},
buttons: {
display: "flex",
justifyContent: "flex-end",
display: 'flex',
justifyContent: 'flex-end',
},
button: {
marginTop: theme.spacing(3),
marginLeft: theme.spacing(1),
},
}));
}))
export default function CheckBalance() {
const classes = useStyles();
const router = useRouter();
const classes = useStyles()
const router = useRouter()
const { client } = useContext(ValidatorClientContext);
const { client } = useContext(ValidatorClientContext)
const { getBalance, isBalanceLoading, balanceCheckError, printedBalance } =
useGetBalance();
useGetBalance()
useEffect(() => {
const updateBalance = async () => {
if (client === null) {
await router.push("/");
await router.push('/')
} else {
await getBalance();
await getBalance()
}
};
updateBalance();
}, [client]);
}
updateBalance()
}, [client])
const balanceMessage = `Current account balance is ${printedBalance}`;
const balanceMessage = `Current account balance is ${printedBalance}`
return (
<React.Fragment>
<>
<MainNav />
<main className={classes.layout}>
<Paper className={classes.paper}>
<Typography component="h1" variant="h4" align="center">
<Typography component='h1' variant='h4' align='center'>
Check Balance
</Typography>
{client === null ? (
<NoClientError />
) : (
<React.Fragment>
<>
<Confirmation
isLoading={isBalanceLoading}
error={balanceCheckError}
progressMessage="Checking balance..."
progressMessage='Checking balance...'
successMessage={balanceMessage}
failureMessage="Failed to check the account balance!"
failureMessage='Failed to check the account balance!'
/>
<div className={classes.buttons}>
<Button
variant="contained"
color="primary"
type="submit"
variant='contained'
color='primary'
type='submit'
onClick={getBalance}
disabled={isBalanceLoading}
className={classes.button}
@@ -99,10 +99,10 @@ export default function CheckBalance() {
Refresh
</Button>
</div>
</React.Fragment>
</>
)}
</Paper>
</main>
</React.Fragment>
);
</>
)
}