Add minting stats (hardcoded, WIP)

This commit is contained in:
Nicola Benaglia 2025-06-07 00:50:41 +02:00
parent f9a51333d6
commit 50f03f1488
2 changed files with 147 additions and 73 deletions

View File

@ -3978,13 +3978,11 @@ function App() {
)} )}
{isOpenMinting && ( {isOpenMinting && (
// <Minting <Minting
// setIsOpenMinting={setIsOpenMinting} setIsOpenMinting={setIsOpenMinting}
// myAddress={address} myAddress={address}
// show={show} show={show}
// /> />
<MintingDetailsPage />
)} )}
{!isAuthenticated && ( {!isAuthenticated && (

View File

@ -4,17 +4,20 @@ import {
Box, Box,
Button, Button,
Card, Card,
Container,
Dialog, Dialog,
DialogActions, DialogActions,
DialogContent, DialogContent,
DialogTitle, DialogTitle,
Divider, Divider,
IconButton, IconButton,
Paper,
Snackbar, Snackbar,
Toolbar, Toolbar,
Typography, Typography,
useTheme, useTheme,
} from '@mui/material'; } from '@mui/material';
import Grid from '@mui/material/Grid';
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import { getBaseApiReact } from '../../App'; import { getBaseApiReact } from '../../App';
@ -37,14 +40,11 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
const [mintingAccounts, setMintingAccounts] = useState([]); const [mintingAccounts, setMintingAccounts] = useState([]);
const [accountInfo, setAccountInfo] = useState(null); const [accountInfo, setAccountInfo] = useState(null);
const [rewardSharePublicKey, setRewardSharePublicKey] = useState('');
const [mintingKey, setMintingKey] = useState(''); const [mintingKey, setMintingKey] = useState('');
const [rewardsharekey, setRewardsharekey] = useState('');
const [rewardShares, setRewardShares] = useState([]); const [rewardShares, setRewardShares] = useState([]);
const [nodeInfos, setNodeInfos] = useState({}); const [nodeInfos, setNodeInfos] = useState({});
const [openSnack, setOpenSnack] = useState(false); const [openSnack, setOpenSnack] = useState(false);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
const { show: showKey, message } = useModal();
const { isShow: isShowNext, onOk, show: showNext } = useModal(); const { isShow: isShowNext, onOk, show: showNext } = useModal();
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation([ const { t } = useTranslation([
@ -161,13 +161,13 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
return address; return address;
}; };
const handleAccountInfos = (address, field) => { // const handleAccountInfos = (address, field) => {
if (!address) return undefined; // if (!address) return undefined;
if (accountInfos[address]) return accountInfos[address]?.[field]; // if (accountInfos[address]) return accountInfos[address]?.[field];
if (accountInfos[address] === null) return undefined; // if (accountInfos[address] === null) return undefined;
getAccountInfo(address, true); // getAccountInfo(address, true);
return undefined; // return undefined;
}; // };
const calculateBlocksRemainingToLevel1 = (address) => { const calculateBlocksRemainingToLevel1 = (address) => {
if (!address) return undefined; if (!address) return undefined;
@ -308,6 +308,7 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
const createRewardShare = useCallback(async (publicKey, recipient) => { const createRewardShare = useCallback(async (publicKey, recipient) => {
const fee = await getFee('REWARD_SHARE'); const fee = await getFee('REWARD_SHARE');
await show({ await show({
message: t('core:message.question.perform_transaction', { message: t('core:message.question.perform_transaction', {
action: 'REWARD_SHARE', action: 'REWARD_SHARE',
@ -315,6 +316,7 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
}), }),
publishFee: fee.fee + ' QORT', publishFee: fee.fee + ' QORT',
}); });
return await new Promise((res, rej) => { return await new Promise((res, rej) => {
window window
.sendMessage('createRewardShare', { .sendMessage('createRewardShare', {
@ -382,7 +384,6 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
const waitUntilRewardShareIsConfirmed = async (timeoutMs = 600000) => { const waitUntilRewardShareIsConfirmed = async (timeoutMs = 600000) => {
const pollingInterval = 30000; const pollingInterval = 30000;
const startTime = Date.now(); const startTime = Date.now();
const sleep = (ms) => new Promise((res) => setTimeout(res, ms)); const sleep = (ms) => new Promise((res) => setTimeout(res, ms));
while (Date.now() - startTime < timeoutMs) { while (Date.now() - startTime < timeoutMs) {
@ -424,9 +425,11 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
await showNext({ await showNext({
message: '', message: '',
}); });
const privateRewardShare = await getRewardSharePrivateKey( const privateRewardShare = await getRewardSharePrivateKey(
accountInfo?.publicKey accountInfo?.publicKey
); );
setShowWaitDialog(false); setShowWaitDialog(false);
addMintingAccount(privateRewardShare); addMintingAccount(privateRewardShare);
} }
@ -446,61 +449,61 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
} }
}; };
const getPublicKeyFromAddress = async (address) => { // const getPublicKeyFromAddress = async (address) => {
const url = `${getBaseApiReact()}/addresses/publickey/${address}`; // const url = `${getBaseApiReact()}/addresses/publickey/${address}`;
const response = await fetch(url); // const response = await fetch(url);
const data = await response.text(); // const data = await response.text();
return data; // return data;
}; // };
const checkIfMinterGroup = async (address) => { // const checkIfMinterGroup = async (address) => {
const url = `${getBaseApiReact()}/groups/member/${address}`; // const url = `${getBaseApiReact()}/groups/member/${address}`;
const response = await fetch(url); // const response = await fetch(url);
const data = await response.json(); // const data = await response.json();
return !!data?.find((grp) => grp?.groupId?.toString() === '694'); // return !!data?.find((grp) => grp?.groupId?.toString() === '694');
}; // };
const removeRewardShare = useCallback(async (rewardShare) => { // const removeRewardShare = useCallback(async (rewardShare) => {
return await new Promise((res, rej) => { // return await new Promise((res, rej) => {
window // window
.sendMessage('removeRewardShare', { // .sendMessage('removeRewardShare', {
rewardShareKeyPairPublicKey: rewardShare.rewardSharePublicKey, // rewardShareKeyPairPublicKey: rewardShare.rewardSharePublicKey,
recipient: rewardShare.recipient, // recipient: rewardShare.recipient,
percentageShare: -1, // percentageShare: -1,
}) // })
.then((response) => { // .then((response) => {
if (!response?.error) { // if (!response?.error) {
res(response); // res(response);
setTxList((prev) => [ // setTxList((prev) => [
{ // {
...rewardShare, // ...rewardShare,
...response, // ...response,
type: 'remove-rewardShare', // type: 'remove-rewardShare',
label: t('group:message.success.rewardshare_remove', { // label: t('group:message.success.rewardshare_remove', {
postProcess: 'capitalizeFirstChar', // postProcess: 'capitalizeFirstChar',
}), // }),
labelDone: t('group:message.success.rewardshare_remove_label', { // labelDone: t('group:message.success.rewardshare_remove_label', {
postProcess: 'capitalizeFirstChar', // postProcess: 'capitalizeFirstChar',
}), // }),
done: false, // done: false,
}, // },
...prev, // ...prev,
]); // ]);
return; // return;
} // }
rej({ message: response.error }); // rej({ message: response.error });
}) // })
.catch((error) => { // .catch((error) => {
rej({ // rej({
message: // message:
error.message || // error.message ||
t('core:message.error.generic', { // t('core:message.error.generic', {
postProcess: 'capitalizeFirstChar', // postProcess: 'capitalizeFirstChar',
}), // }),
}); // });
}); // });
}); // });
}, []); // }, []);
useEffect(() => { useEffect(() => {
getNodeInfos(); getNodeInfos();
@ -559,6 +562,17 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
return '' + countBlocksString; return '' + countBlocksString;
}; };
const StatCard = ({ label, value }: { label: string; value: string }) => (
<Grid size={{ xs: 12, sm: 6 }}>
<Box textAlign="center">
<Typography variant="subtitle1" fontWeight="bold">
{label}
</Typography>
<Typography>{value}</Typography>
</Box>
</Grid>
);
return ( return (
<Dialog <Dialog
open={true} open={true}
@ -624,6 +638,7 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
/> />
</Box> </Box>
)} )}
<Card <Card
sx={{ sx={{
backgroundColor: theme.palette.background.default, backgroundColor: theme.palette.background.default,
@ -859,6 +874,60 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
</Card> </Card>
)} )}
<Container maxWidth="md" sx={{ py: 4 }}>
<Typography variant="h4" fontWeight="bold" gutterBottom>
General Minting Details
</Typography>
<Paper elevation={3} sx={{ p: 3, mb: 4, borderRadius: '10px' }}>
<Typography variant="h6" gutterBottom>
Blockchain Statistics
</Typography>
<Grid container spacing={2}>
<StatCard label="Avg. Qortal Blocktime" value="72.84 Seconds" />
<StatCard label="Avg. Blocks Per Day" value="1186.16 Blocks" />
<StatCard
label="Avg. Created QORT Per Day"
value="3558.48 QORT"
/>
</Grid>
</Paper>
<Paper elevation={3} sx={{ p: 3, mb: 4, borderRadius: '10px' }}>
<Typography variant="h6" gutterBottom>
Minting Account Details
</Typography>
<Grid container spacing={2}>
<StatCard label="Current Status" value="(Minting)" />
<StatCard label="Current Level" value="Level 4" />
<StatCard label="Blocks To Next Level" value="139467 Blocks" />
</Grid>
<Box mt={2} textAlign="center">
<Typography>
With a 24/7 Minting you will reach level 5 in{' '}
<strong>117.58 days</strong>!
</Typography>
</Box>
</Paper>
<Paper elevation={3} sx={{ p: 3, borderRadius: '10px' }}>
<Typography variant="h6" gutterBottom>
Minting Rewards Info
</Typography>
<Grid container spacing={2}>
<StatCard label="Current Tier" value="Tier 2 (Level 3 + 4)" />
<StatCard label="Total Minters in The Tier" value="77 Minters" />
<StatCard label="Tier Share Per Block" value="13%" />
<StatCard label="Est. Reward Per Block" value="0.00506494 QORT" />
<StatCard label="Est. Reward Per Day" value="6.00782338 QORT" />
</Grid>
</Paper>
</Container>
{showWaitDialog && ( {showWaitDialog && (
<Dialog <Dialog
open={showWaitDialog} open={showWaitDialog}
@ -871,10 +940,16 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
textAlign: 'center', textAlign: 'center',
color: theme.palette.text.primary, color: theme.palette.text.primary,
fontWeight: 'bold', fontWeight: 'bold',
opacity: 1, // TODO translate opacity: 1,
}} }}
> >
{isShowNext ? 'Confirmed' : 'Please Wait'} {isShowNext
? t('core:message.generic.confirmed', {
postProcess: 'capitalizeFirstChar',
})
: t('core:message.generic.wait', {
postProcess: 'capitalizeFirstChar',
})}
</DialogTitle> </DialogTitle>
<DialogContent> <DialogContent>
@ -885,6 +960,7 @@ export const Minting = ({ setIsOpenMinting, myAddress, show }) => {
})} })}
</Typography> </Typography>
)} )}
{isShowNext && ( {isShowNext && (
<Typography> <Typography>
{t('group:message.success.rewardshare_confirmed', { {t('group:message.success.rewardshare_confirmed', {