Skip to content

Commit 73f6743

Browse files
committed
feat: claim fees ui
1 parent 60b067c commit 73f6743

File tree

3 files changed

+239
-8
lines changed

3 files changed

+239
-8
lines changed

applications/tari_dan_wallet_web_ui/src/routes/AssetVault/Components/ActionMenu.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { useAccountsCreateFreeTestCoins } from '../../../api/hooks/useAccounts';
2727
import ClaimBurn from './ClaimBurn';
2828
import useAccountStore from '../../../store/accountStore';
2929
import SendMoney from './SendMoney';
30+
import ClaimFees from './ClaimFees';
3031

3132
function ActionMenu() {
3233
const { mutate } = useAccountsCreateFreeTestCoins();
@@ -49,7 +50,8 @@ function ActionMenu() {
4950
marginBottom: theme.spacing(2),
5051
}}
5152
>
52-
<SendMoney/>
53+
<SendMoney />
54+
<ClaimFees />
5355
<Button variant="outlined" onClick={onClaimFreeCoins}>
5456
Claim Free Testnet Coins
5557
</Button>
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
// Copyright 2022. The Tari Project
2+
//
3+
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
4+
// following conditions are met:
5+
//
6+
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7+
// disclaimer.
8+
//
9+
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
10+
// following disclaimer in the documentation and/or other materials provided with the distribution.
11+
//
12+
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
13+
// products derived from this software without specific prior written permission.
14+
//
15+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
16+
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17+
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18+
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20+
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
21+
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22+
23+
import { useState } from "react";
24+
import { Form } from "react-router-dom";
25+
import Button from "@mui/material/Button";
26+
import CheckBox from "@mui/material/Checkbox";
27+
import TextField from "@mui/material/TextField";
28+
import Dialog from "@mui/material/Dialog";
29+
import DialogContent from "@mui/material/DialogContent";
30+
import DialogTitle from "@mui/material/DialogTitle";
31+
import FormControlLabel from "@mui/material/FormControlLabel";
32+
import Box from "@mui/material/Box";
33+
import { useAccountsList, useAccountsTransfer } from "../../../api/hooks/useAccounts";
34+
import { useTheme } from "@mui/material/styles";
35+
import useAccountStore from "../../../store/accountStore";
36+
import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from "@mui/material";
37+
import { claimFees } from "../../../utils/json_rpc";
38+
import { useKeysList } from "../../../api/hooks/useKeys";
39+
40+
export default function ClaimFees() {
41+
const [open, setOpen] = useState(false);
42+
const [disabled, setDisabled] = useState(false);
43+
const [estimatedFee, setEstimatedFee] = useState(0);
44+
const [claimFeesFormState, setClaimFeesFormState] = useState({
45+
account: "",
46+
fee: "",
47+
validatorNodePublicKey: "",
48+
epoch: "",
49+
key: "",
50+
newAccount: false,
51+
disabled: false,
52+
});
53+
54+
55+
const { data: dataAccountsList } = useAccountsList(0, 10);
56+
const { data: dataKeysList } = useKeysList();
57+
const { setPopup } = useAccountStore();
58+
59+
const theme = useTheme();
60+
61+
const isFormFilled = () => {
62+
if (claimFeesFormState.validatorNodePublicKey.length !== 64) {
63+
return false;
64+
}
65+
return claimFeesFormState.account !== "" && claimFeesFormState.validatorNodePublicKey !== "" && claimFeesFormState.epoch !== "";
66+
};
67+
68+
const is_filled = isFormFilled();
69+
70+
const onClaimFeesKeyChange = (e: SelectChangeEvent<string>) => {
71+
let key = e.target.value;
72+
let key_index = dataKeysList.keys.indexOf(key);
73+
let account = claimFeesFormState.account;
74+
let selected_account = dataAccountsList.accounts.find((account: any) => account.account.key_index === key_index);
75+
let new_account_name;
76+
if (selected_account !== undefined) {
77+
account = selected_account.account.name;
78+
new_account_name = false;
79+
} else {
80+
if (claimFeesFormState.newAccount === false) {
81+
account = "";
82+
}
83+
new_account_name = true;
84+
}
85+
setClaimFeesFormState({
86+
...claimFeesFormState,
87+
"key": key,
88+
"account": account,
89+
"newAccount": new_account_name,
90+
});
91+
};
92+
93+
const onEpochChange = (e: React.ChangeEvent<HTMLInputElement>) => {
94+
if (/^[0-9]*$/.test(e.target.value)) {
95+
setClaimFeesFormState({
96+
...claimFeesFormState,
97+
[e.target.name]: e.target.value,
98+
});
99+
}
100+
}
101+
102+
const onClaimBurnAccountNameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
103+
setClaimFeesFormState({
104+
...claimFeesFormState,
105+
[e.target.name]: e.target.value,
106+
});
107+
}
108+
109+
const onPublicKeyChange = (e: React.ChangeEvent<HTMLInputElement>) => {
110+
if (/^[0-9a-fA-F]*$/.test(e.target.value)) {
111+
setClaimFeesFormState({
112+
...claimFeesFormState,
113+
[e.target.name]: e.target.value,
114+
});
115+
}
116+
setEstimatedFee(0);
117+
};
118+
119+
const onClaim = async () => {
120+
if (claimFeesFormState.account) {
121+
setDisabled(true);
122+
claimFees(claimFeesFormState.account, 3000, claimFeesFormState.validatorNodePublicKey, parseInt(claimFeesFormState.epoch)).then((resp) => {
123+
console.log(resp);
124+
}).catch((e) => {
125+
console.error(e);
126+
}).finally(() => {
127+
setDisabled(false);
128+
});
129+
};
130+
}
131+
132+
const handleClickOpen = () => {
133+
setOpen(true);
134+
};
135+
136+
const handleClose = () => {
137+
setOpen(false);
138+
};
139+
140+
const formattedKey = (key: any[]) => {
141+
let account = dataAccountsList.accounts.find((account: any) => account.account.key_index === +key[0])
142+
if (account === undefined) {
143+
return null
144+
return <div><b>{key[0]}</b> {key[1]}</div>
145+
}
146+
return <div><b>{key[0]}</b> {key[1]}<br></br>Account <i>{account.account.name}</i></div>
147+
}
148+
149+
return (
150+
<div>
151+
<Button variant="outlined" onClick={handleClickOpen}>
152+
Claim Fees
153+
</Button>
154+
<Dialog open={open} onClose={handleClose}>
155+
<DialogTitle>Claim Fees</DialogTitle>
156+
<DialogContent className="dialog-content">
157+
<Form onSubmit={onClaim} className="flex-container-vertical" style={{ paddingTop: theme.spacing(1) }}>
158+
<FormControl>
159+
<InputLabel id="key">Key</InputLabel>
160+
<Select
161+
labelId="key"
162+
name="key"
163+
label="Key"
164+
value={claimFeesFormState.key}
165+
onChange={onClaimFeesKeyChange}
166+
style={{ flexGrow: 1, minWidth: "200px" }}
167+
disabled={claimFeesFormState.disabled}
168+
>
169+
{dataKeysList?.keys?.map((key: any) => (
170+
<MenuItem key={key} value={key}>
171+
{formattedKey(key)}
172+
</MenuItem>
173+
))}
174+
</Select>
175+
</FormControl>
176+
<TextField name="account"
177+
label="Account Name"
178+
value={claimFeesFormState.account}
179+
onChange={onClaimBurnAccountNameChange}
180+
style={{ flexGrow: 1 }}
181+
disabled={claimFeesFormState.disabled || !claimFeesFormState.newAccount}>
182+
</TextField>
183+
<TextField
184+
name="fee"
185+
label="Fee"
186+
value={estimatedFee || "Press fee estimate to calculate"}
187+
style={{ flexGrow: 1 }}
188+
InputProps={{ readOnly: true }}
189+
disabled={disabled}
190+
/>
191+
<TextField
192+
name="validatorNodePublicKey"
193+
label="Validator Node Public Key"
194+
value={claimFeesFormState.validatorNodePublicKey}
195+
onChange={onPublicKeyChange}
196+
style={{ flexGrow: 1 }}
197+
disabled={disabled}
198+
/>
199+
<TextField
200+
name="epoch"
201+
label="Epoch"
202+
value={claimFeesFormState.epoch}
203+
style={{ flexGrow: 1 }}
204+
onChange={onEpochChange}
205+
disabled={disabled}
206+
/>
207+
<Box
208+
className="flex-container"
209+
style={{
210+
justifyContent: "flex-end",
211+
}}
212+
>
213+
<Button variant="outlined" onClick={handleClose} disabled={disabled}>
214+
Cancel
215+
</Button>
216+
<Button variant="contained" type="submit" disabled={disabled || !is_filled}>
217+
{estimatedFee ? "Claim" : "Estimate fee"}
218+
</Button>
219+
</Box>
220+
</Form>
221+
</DialogContent>
222+
</Dialog>
223+
</div>
224+
);
225+
}

applications/tari_dan_wallet_web_ui/src/utils/json_rpc.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,13 @@ async function internalJsonRpc(method: string, token: any = null, params: any =
3434
id = json_id;
3535
json_id += 1;
3636
});
37-
let address = "http://localhost:9000";
38-
try {
39-
address = await (await fetch('/json_rpc_address')).text();
40-
if (!address.startsWith("http")) {
41-
address = "http://" + address;
42-
}
43-
} catch { }
37+
let address = "http://127.0.0.1:18016";
38+
// try {
39+
// address = await (await fetch('/json_rpc_address')).text();
40+
// if (!address.startsWith("http")) {
41+
// address = "http://" + address;
42+
// }
43+
// } catch { }
4444
let headers: { [key: string]: string } = {
4545
"Content-Type": "application/json",
4646
};
@@ -185,3 +185,7 @@ export const accountNFTsList = (offset: number, limit: number) => jsonRpc("nfts.
185185
// settings
186186
export const getSettings = () => jsonRpc("settings.get", []);
187187
export const setSettings = (settings: any) => jsonRpc("settings.set", settings);
188+
189+
// validators
190+
export const getFeeSummary = (validatorPublicKey: string, minEpoch: number, maxEpoch: number) => jsonRpc("validators.get_fee_summary", [validatorPublicKey, minEpoch, maxEpoch]);
191+
export const claimFees = (account: string, maxFee: number, validatorPublicKey: string, epoch: number) => jsonRpc("validators.claim_fees", [account, maxFee, validatorPublicKey, epoch]);

0 commit comments

Comments
 (0)