Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored register node function #20

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 162 additions & 61 deletions build/ui/src/components/Setup/RegisterNode.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import React, { useState, useEffect } from "react";
import { Typography, Button, Chip, Box, TextField, CircularProgress, Link } from "@mui/material";
import {
Typography,
Button,
Chip,
Box,
TextField,
CircularProgress,
Link,
} from "@mui/material";
import OpenInNewIcon from "@mui/icons-material/OpenInNew";
import CopyToClipboardButton from "../Buttons/CopyToClipboardButton";
import { AppService } from "../../services/AppService";
import { RocketpoolData } from "../../types/RocketpoolData";
import { CanRegisterNode } from "../../types/CanRegisterNode";
import { enoughEthBalance, isValidEthAddress, toEther, toEtherString } from "../../utils/Utils";
import {
enoughEthBalance,
isValidEthAddress,
toEtherString,
} from "../../utils/Utils";
import { NodeCanSetWithdrawalAddress } from "../../types/NodeCanSetWithdrawalAddress";
import { RocketpoolContext } from "../Providers/Context";
import { TxResponse } from "../../types/TxResponse";
Expand All @@ -25,13 +37,16 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
const [actionsEnabled, setActionsEnabled] = useState<boolean>(true);
const [canRegisterNode, setCanRegisterNode] = useState<CanRegisterNode>();
const [txResponse, setTxResponse] = useState<TxResponse>();
const [canSetWithdrawalAddress, setCanSetWithdrawalAddress] = useState<NodeCanSetWithdrawalAddress>();
const [canSetWithdrawalAddress, setCanSetWithdrawalAddress] =
useState<NodeCanSetWithdrawalAddress>();
const [addressEntered, setAddressEntered] = useState<string>("");
const [addressError, setAddressError] = useState<string>("");
const { rocketpoolValue, updateRocketpoolValue } = React.useContext(RocketpoolContext);
const { rocketpoolValue, updateRocketpoolValue } =
React.useContext(RocketpoolContext);

const minimumRpl8Eth = data?.networkRplPrice?.minPer8EthMinipoolRplStake ?? 0;
const minimumRpl16Eth = data?.networkRplPrice?.minPer16EthMinipoolRplStake ?? 0;
const minimumRpl16Eth =
data?.networkRplPrice?.minPer16EthMinipoolRplStake ?? 0;
const minimumRpl = Math.min(minimumRpl8Eth, minimumRpl16Eth);
const ethBalance = data?.nodeStatus?.accountBalances.eth ?? 0;
const rplBalance = data?.nodeStatus?.accountBalances.rpl ?? 0;
Expand All @@ -42,62 +57,127 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
var canRegisterNode = await appService.canRegisterNode();
setCanRegisterNode(canRegisterNode);
setActionsEnabled(canRegisterNode.canRegister);
};
}

useEffect(() => {
fetchData();
}, [data]);

const handleRegisterNodeClick = async () => {
setTxs([]);
setIsLoading(true);
setActionsEnabled(false);

try {
setTxs([]);
setIsLoading(true);
setActionsEnabled(false);
var canNodeRegister = await appService.canRegisterNode();
if (!canNodeRegister.canRegister) { return }
var tx = await appService.nodeRegister();
console.log(tx)
setTxResponse(tx);
if (tx.status !== "success") { return }
setTxs([...txs, tx.txHash]);
var waitResponse = await appService.wait(tx.txHash);
if (waitResponse.status !== "success") { return }
var canWithdrawalRegister = await appService.getNodeCanSetWithdrawalAddress(addressEntered);
setCanSetWithdrawalAddress(canWithdrawalRegister);
if (!canWithdrawalRegister.canSet) { return }
tx = await appService.nodeSetWithdrawalAddress(addressEntered);
setTxResponse(tx);
if (tx.status !== "success") { return }
setTxs([...txs, tx.txHash]);
waitResponse = await appService.wait(tx.txHash);
var canSetSmoothingPool = await appService.getNodeCanSetSmoothingPoolStatus();
if (canSetSmoothingPool.status !== "success") { return }
tx = await appService.nodeSetSmoothingPoolStatus();
console.log(tx);
setTxResponse(tx);
if (tx.status !== "success") { return }
setTxs([...txs, tx.txHash]);
waitResponse = await appService.wait(tx.txHash);
await checkCanNodeRegister();

await registerNode();

await checkCanSetWithdrawalAddress();

await setWithdrawalAddress();

await checkCanSetSmoothingPoolStatus();

await setSmoothingPoolStatus();
} finally {
setIsLoading(false);
setActionsEnabled(true);
setCanSetWithdrawalAddress(undefined);
var walletStatus = await appService.getWalletStatus();
var nodeStatus = await appService.getNodeStatus();
const walletStatus = await appService.getWalletStatus();
const nodeStatus = await appService.getNodeStatus();
updateRocketpoolValue(
new RocketpoolData(
rocketpoolValue?.network,
walletStatus,
nodeStatus,
rocketpoolValue?.nodeSync,
rocketpoolValue?.networkRplPrice,
rocketpoolValue?.networkRplPrice
)
);
}
};

async function checkCanNodeRegister() {
const { canRegister } = await appService.canRegisterNode();
if (!canRegister) {
throw new Error("Cannot register node");
}
}

async function registerNode() {
const registrationTx = await appService.nodeRegister();
console.debug(registrationTx);
setTxResponse(registrationTx);

if (registrationTx.status !== "success") {
throw new Error("Call to nodeRegister failed");
}

setTxs([...txs, registrationTx.txHash]);

const waitResponse = await appService.wait(registrationTx.txHash);

if (waitResponse.status !== "success") {
throw new Error("Call to wait failed");
}
}

async function checkCanSetWithdrawalAddress() {
const canSetWithdrawalAddress =
await appService.getNodeCanSetWithdrawalAddress(addressEntered);

setCanSetWithdrawalAddress(canSetWithdrawalAddress);

if (!canSetWithdrawalAddress.canSet) {
throw new Error("Cannot set withdrawal address");
}
}

async function setWithdrawalAddress() {
const setWithdrawalAddressTx = await appService.nodeSetWithdrawalAddress(
addressEntered
);

console.debug(setWithdrawalAddressTx);

setTxResponse(setWithdrawalAddressTx);

if (setWithdrawalAddressTx.status !== "success") {
throw new Error("Call to nodeSetWithdrawalAddress failed");
}
setTxs([...txs, setWithdrawalAddressTx.txHash]);

await appService.wait(setWithdrawalAddressTx.txHash);
}

async function checkCanSetSmoothingPoolStatus() {
const canSetSmoothingPool =
await appService.getNodeCanSetSmoothingPoolStatus();

if (canSetSmoothingPool.status !== "success") {
throw new Error("Call to getNodeCanSetSmoothingPoolStatus failed");
}
}

async function setSmoothingPoolStatus() {
const setSmoothingPoolStatusTx =
await appService.nodeSetSmoothingPoolStatus();
console.debug(setSmoothingPoolStatusTx);
setTxResponse(setSmoothingPoolStatusTx);

if (setSmoothingPoolStatusTx.status !== "success") {
throw new Error("Call to nodeSetSmoothingPoolStatus failed");
}
setTxs([...txs, setSmoothingPoolStatusTx.txHash]);
await appService.wait(setSmoothingPoolStatusTx.txHash);
}

const isValidAddressEntered = (address: string) => {
return isValidEthAddress(address) && (address !== data?.walletStatus?.accountAddress);
return (
isValidEthAddress(address) &&
address !== data?.walletStatus?.accountAddress
);
};

const handleAddressChange = (event: any) => {
Expand All @@ -106,23 +186,26 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
if (!isValidAddressEntered(newValue)) {
setAddressError(`${newValue} is not a valid Ethereum address`);
} else {
setAddressError('');
setAddressError("");
}
};

const enoughTokens = () => {
return enoughEthBalance(data?.nodeStatus, data?.networkRplPrice) && enoughRpl;
return (
enoughEthBalance(data?.nodeStatus, data?.networkRplPrice) && enoughRpl
);
};

return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
minHeight: "100vh",
'& > * + *': { marginTop: '15px' }
}}>
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
minHeight: "100vh",
"& > * + *": { marginTop: "15px" },
}}
>
<>
<Typography variant="body1">
You must have enough ETH and RPL in order to Register your node
Expand All @@ -131,17 +214,17 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
<Typography variant="body1">
Transfer tokens to your address:{" "}
<strong>{data?.walletStatus?.accountAddress}</strong>
<CopyToClipboardButton value={data?.walletStatus?.accountAddress} fontSize="small" />
<CopyToClipboardButton
value={data?.walletStatus?.accountAddress}
fontSize="small"
/>
</Typography>
<div>
<Typography variant="h6">
Balances
</Typography>
<Typography variant="h6">Balances</Typography>
<Chip
label={`${toEtherString(ethBalance)} ETH`}
color={enoughEthBalance() ? "primary" : "error"}
/>
{' '}
/>{" "}
<Chip
label={`${toEtherString(rplBalance)} RPL`}
color={enoughRpl ? "primary" : "error"}
Expand All @@ -153,7 +236,8 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
Configure your withdrawal address
</Typography>
<Typography variant="body1">
The withdrawal address must be an address of which we are certain we have access and the private key.
The withdrawal address must be an address of which we are certain we
have access and the private key.
</Typography>
</div>
<TextField
Expand All @@ -167,15 +251,32 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
sx={{ marginTop: 2 }}
/>
<br />
<Button
disabled={!canRegisterNode?.canRegister || !enoughTokens() || !isValidAddressEntered(addressEntered) || !actionsEnabled || isLoading}
variant="contained"
onClick={() => handleRegisterNodeClick()}>
<Button
disabled={
!canRegisterNode?.canRegister ||
!enoughTokens() ||
!isValidAddressEntered(addressEntered) ||
!actionsEnabled ||
isLoading
}
variant="contained"
onClick={() => handleRegisterNodeClick()}
>
{" "}
{isLoading ? <CircularProgress size={24} color="primary" /> : 'Register node'}
{isLoading ? (
<CircularProgress size={24} color="primary" />
) : (
"Register node"
)}
</Button>
{txs.map((tx, index) => (
<Link href={`https://goerli.etherscan.io/tx/${tx}`} variant="subtitle1" underline="always" target="_blank" rel="noopener">
<Link
href={`https://goerli.etherscan.io/tx/${tx}`}
variant="subtitle1"
underline="always"
target="_blank"
rel="noopener"
>
View transaction {index + 1} on Etherscan
<OpenInNewIcon fontSize="inherit" />
</Link>
Expand All @@ -198,6 +299,6 @@ const RegisterNode: React.FC<RegisterNodeProps> = ({
</>
</Box>
);
}
};

export default RegisterNode;