Skip to content

Commit

Permalink
feat: claim fees ui
Browse files Browse the repository at this point in the history
  • Loading branch information
Cifko committed Jan 16, 2024
1 parent 60b067c commit 73f6743
Show file tree
Hide file tree
Showing 3 changed files with 239 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { useAccountsCreateFreeTestCoins } from '../../../api/hooks/useAccounts';
import ClaimBurn from './ClaimBurn';
import useAccountStore from '../../../store/accountStore';
import SendMoney from './SendMoney';
import ClaimFees from './ClaimFees';

function ActionMenu() {
const { mutate } = useAccountsCreateFreeTestCoins();
Expand All @@ -49,7 +50,8 @@ function ActionMenu() {
marginBottom: theme.spacing(2),
}}
>
<SendMoney/>
<SendMoney />
<ClaimFees />
<Button variant="outlined" onClick={onClaimFreeCoins}>
Claim Free Testnet Coins
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// Copyright 2022. The Tari Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
// following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
// disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
// following disclaimer in the documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
// products derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import { useState } from "react";
import { Form } from "react-router-dom";
import Button from "@mui/material/Button";
import CheckBox from "@mui/material/Checkbox";
import TextField from "@mui/material/TextField";
import Dialog from "@mui/material/Dialog";
import DialogContent from "@mui/material/DialogContent";
import DialogTitle from "@mui/material/DialogTitle";
import FormControlLabel from "@mui/material/FormControlLabel";
import Box from "@mui/material/Box";
import { useAccountsList, useAccountsTransfer } from "../../../api/hooks/useAccounts";
import { useTheme } from "@mui/material/styles";
import useAccountStore from "../../../store/accountStore";
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material";
import { claimFees } from "../../../utils/json_rpc";
import { useKeysList } from "../../../api/hooks/useKeys";

export default function ClaimFees() {
const [open, setOpen] = useState(false);
const [disabled, setDisabled] = useState(false);
const [estimatedFee, setEstimatedFee] = useState(0);
const [claimFeesFormState, setClaimFeesFormState] = useState({
account: "",
fee: "",
validatorNodePublicKey: "",
epoch: "",
key: "",
newAccount: false,
disabled: false,
});


const { data: dataAccountsList } = useAccountsList(0, 10);
const { data: dataKeysList } = useKeysList();
const { setPopup } = useAccountStore();

const theme = useTheme();

const isFormFilled = () => {
if (claimFeesFormState.validatorNodePublicKey.length !== 64) {
return false;
}
return claimFeesFormState.account !== "" && claimFeesFormState.validatorNodePublicKey !== "" && claimFeesFormState.epoch !== "";
};

const is_filled = isFormFilled();

const onClaimFeesKeyChange = (e: SelectChangeEvent<string>) => {
let key = e.target.value;
let key_index = dataKeysList.keys.indexOf(key);
let account = claimFeesFormState.account;
let selected_account = dataAccountsList.accounts.find((account: any) => account.account.key_index === key_index);
let new_account_name;
if (selected_account !== undefined) {
account = selected_account.account.name;
new_account_name = false;
} else {
if (claimFeesFormState.newAccount === false) {
account = "";
}
new_account_name = true;
}
setClaimFeesFormState({
...claimFeesFormState,
"key": key,
"account": account,
"newAccount": new_account_name,
});
};

const onEpochChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (/^[0-9]*$/.test(e.target.value)) {
setClaimFeesFormState({
...claimFeesFormState,
[e.target.name]: e.target.value,
});
}
}

const onClaimBurnAccountNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setClaimFeesFormState({
...claimFeesFormState,
[e.target.name]: e.target.value,
});
}

const onPublicKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (/^[0-9a-fA-F]*$/.test(e.target.value)) {
setClaimFeesFormState({
...claimFeesFormState,
[e.target.name]: e.target.value,
});
}
setEstimatedFee(0);
};

const onClaim = async () => {
if (claimFeesFormState.account) {
setDisabled(true);
claimFees(claimFeesFormState.account, 3000, claimFeesFormState.validatorNodePublicKey, parseInt(claimFeesFormState.epoch)).then((resp) => {
console.log(resp);
}).catch((e) => {
console.error(e);
}).finally(() => {
setDisabled(false);
});
};
}

const handleClickOpen = () => {
setOpen(true);
};

const handleClose = () => {
setOpen(false);
};

const formattedKey = (key: any[]) => {
let account = dataAccountsList.accounts.find((account: any) => account.account.key_index === +key[0])
if (account === undefined) {
return null
return <div><b>{key[0]}</b> {key[1]}</div>
}
return <div><b>{key[0]}</b> {key[1]}<br></br>Account <i>{account.account.name}</i></div>
}

return (
<div>
<Button variant="outlined" onClick={handleClickOpen}>
Claim Fees
</Button>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Claim Fees</DialogTitle>
<DialogContent className="dialog-content">
<Form onSubmit={onClaim} className="flex-container-vertical" style={{ paddingTop: theme.spacing(1) }}>
<FormControl>
<InputLabel id="key">Key</InputLabel>
<Select
labelId="key"
name="key"
label="Key"
value={claimFeesFormState.key}
onChange={onClaimFeesKeyChange}
style={{ flexGrow: 1, minWidth: "200px" }}
disabled={claimFeesFormState.disabled}
>
{dataKeysList?.keys?.map((key: any) => (
<MenuItem key={key} value={key}>
{formattedKey(key)}
</MenuItem>
))}
</Select>
</FormControl>
<TextField name="account"
label="Account Name"
value={claimFeesFormState.account}
onChange={onClaimBurnAccountNameChange}
style={{ flexGrow: 1 }}
disabled={claimFeesFormState.disabled || !claimFeesFormState.newAccount}>
</TextField>
<TextField
name="fee"
label="Fee"
value={estimatedFee || "Press fee estimate to calculate"}
style={{ flexGrow: 1 }}
InputProps={{ readOnly: true }}
disabled={disabled}
/>
<TextField
name="validatorNodePublicKey"
label="Validator Node Public Key"
value={claimFeesFormState.validatorNodePublicKey}
onChange={onPublicKeyChange}
style={{ flexGrow: 1 }}
disabled={disabled}
/>
<TextField
name="epoch"
label="Epoch"
value={claimFeesFormState.epoch}
style={{ flexGrow: 1 }}
onChange={onEpochChange}
disabled={disabled}
/>
<Box
className="flex-container"
style={{
justifyContent: "flex-end",
}}
>
<Button variant="outlined" onClick={handleClose} disabled={disabled}>
Cancel
</Button>
<Button variant="contained" type="submit" disabled={disabled || !is_filled}>
{estimatedFee ? "Claim" : "Estimate fee"}
</Button>
</Box>
</Form>
</DialogContent>
</Dialog>
</div>
);
}
18 changes: 11 additions & 7 deletions applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ async function internalJsonRpc(method: string, token: any = null, params: any =
id = json_id;
json_id += 1;
});
let address = "http://localhost:9000";
try {
address = await (await fetch('/json_rpc_address')).text();
if (!address.startsWith("http")) {
address = "http://" + address;
}
} catch { }
let address = "http://127.0.0.1:18016";
// try {
// address = await (await fetch('/json_rpc_address')).text();
// if (!address.startsWith("http")) {
// address = "http://" + address;
// }
// } catch { }
let headers: { [key: string]: string } = {
"Content-Type": "application/json",
};
Expand Down Expand Up @@ -185,3 +185,7 @@ export const accountNFTsList = (offset: number, limit: number) => jsonRpc("nfts.
// settings
export const getSettings = () => jsonRpc("settings.get", []);
export const setSettings = (settings: any) => jsonRpc("settings.set", settings);

// validators
export const getFeeSummary = (validatorPublicKey: string, minEpoch: number, maxEpoch: number) => jsonRpc("validators.get_fee_summary", [validatorPublicKey, minEpoch, maxEpoch]);
export const claimFees = (account: string, maxFee: number, validatorPublicKey: string, epoch: number) => jsonRpc("validators.claim_fees", [account, maxFee, validatorPublicKey, epoch]);

0 comments on commit 73f6743

Please sign in to comment.