apy playground ui

update calc button style

validator-api-client and wallet: compute mixnode reward estimation
This commit is contained in:
fmtabbara
2022-09-16 12:33:56 +01:00
parent b9e52d22d1
commit fe223b5a60
6 changed files with 199 additions and 5 deletions
@@ -9,10 +9,11 @@ use nym_api_requests::coconut::{
BlindSignRequestBody, BlindedSignatureResponse, VerifyCredentialBody, VerifyCredentialResponse,
};
use nym_api_requests::models::{
GatewayCoreStatusResponse, GatewayStatusReportResponse, GatewayUptimeHistoryResponse,
InclusionProbabilityResponse, MixNodeBondAnnotated, MixnodeCoreStatusResponse,
MixnodeStatusReportResponse, MixnodeStatusResponse, MixnodeUptimeHistoryResponse, RequestError,
RewardEstimationResponse, StakeSaturationResponse, UptimeResponse,
ComputeRewardEstParam, GatewayCoreStatusResponse, GatewayStatusReportResponse,
GatewayUptimeHistoryResponse, InclusionProbabilityResponse, MixNodeBondAnnotated,
MixnodeCoreStatusResponse, MixnodeStatusReportResponse, MixnodeStatusResponse,
MixnodeUptimeHistoryResponse, RequestError, RewardEstimationResponse, StakeSaturationResponse,
UptimeResponse,
};
use reqwest::Response;
use serde::{Deserialize, Serialize};
@@ -361,6 +362,25 @@ impl Client {
.await
}
pub async fn compute_mixnode_reward_estimation(
&self,
identity: IdentityKeyRef<'_>,
request_body: &ComputeRewardEstParam,
) -> Result<RewardEstimationResponse, ValidatorAPIError> {
self.post_validator_api(
&[
routes::API_VERSION,
routes::STATUS_ROUTES,
routes::MIXNODE,
identity,
routes::COMPUTE_REWARD_ESTIMATION,
],
NO_PARAMS,
request_body,
)
.await
}
pub async fn get_mixnode_stake_saturation(
&self,
mix_id: MixId,
@@ -28,6 +28,7 @@ pub const STATUS: &str = "status";
pub const REPORT: &str = "report";
pub const HISTORY: &str = "history";
pub const REWARD_ESTIMATION: &str = "reward-estimation";
pub const COMPUTE_REWARD_ESTIMATION: &str = "compute-reward-estimation";
pub const AVG_UPTIME: &str = "avg_uptime";
pub const STAKE_SATURATION: &str = "stake-saturation";
pub const INCLUSION_CHANCE: &str = "inclusion-probability";
+1
View File
@@ -99,6 +99,7 @@ fn main() {
utils::get_old_and_incorrect_hardcoded_fee,
utils::try_convert_pubkey_to_mix_id,
utils::default_mixnode_cost_params,
nym_api::status::compute_mixnode_reward_estimation,
nym_api::status::gateway_core_node_status,
nym_api::status::mixnode_core_node_status,
nym_api::status::mixnode_inclusion_probability,
@@ -8,7 +8,7 @@ use mixnet_contract_common::{IdentityKeyRef, MixId};
use validator_client::models::{
GatewayCoreStatusResponse, GatewayStatusReportResponse, InclusionProbabilityResponse,
MixnodeCoreStatusResponse, MixnodeStatusResponse, RewardEstimationResponse,
StakeSaturationResponse,
StakeSaturationResponse, ComputeRewardEstParam
};
#[tauri::command]
@@ -59,6 +59,26 @@ pub async fn mixnode_reward_estimation(
.await?)
}
#[tauri::command]
pub async fn compute_mixnode_reward_estimation(
identity: &str,
uptime: Option<u8>,
is_active: Option<bool>,
pledge_amount: Option<u64>,
total_delegation: Option<u64>,
state: tauri::State<'_, WalletState>,
) -> Result<RewardEstimationResponse, BackendError> {
let request_body = ComputeRewardEstParam {
uptime,
is_active,
pledge_amount,
total_delegation,
};
Ok(api_client!(state)
.compute_mixnode_reward_estimation(identity, &request_body)
.await?)
}
#[tauri::command]
pub async fn mixnode_stake_saturation(
mix_id: MixId,
@@ -0,0 +1,151 @@
import React, { useState } from 'react';
import {
Box,
Button,
Card,
CardActions,
CardContent,
CardHeader,
Divider,
Grid,
Stack,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow,
TextField,
Typography,
} from '@mui/material';
const tableHeader = [
{ title: 'Estimated rewards', bold: true },
{ title: 'Per day' },
{ title: 'Per month' },
{ title: 'Per year' },
];
const tableRows = [
{ title: 'Total node reward', perDay: '10 NYM', perMonth: '300 NYM', perYear: '3600 NYM' },
{ title: 'Operator rewards', perDay: '10 NYM', perMonth: '300 NYM', perYear: '3600 NYM' },
{ title: 'Delegator rewards', perDay: '10 NYM', perMonth: '300 NYM', perYear: '3600 NYM' },
];
const ResultsTable = () => (
<Card variant="outlined" sx={{ p: 1 }}>
<CardContent>
<TableContainer>
<Table>
<TableHead>
<TableRow>
{tableHeader.map((header) => (
<TableCell>
<Typography fontWeight={header.bold ? 'bold' : 'regular'}>{header.title}</Typography>
</TableCell>
))}
</TableRow>
</TableHead>
<TableBody>
{tableRows.map((row) => (
<TableRow>
<TableCell>{row.title}</TableCell>
<TableCell>{row.perDay}</TableCell>
<TableCell>{row.perMonth}</TableCell>
<TableCell>{row.perYear}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</CardContent>
</Card>
);
const NodeDetails = ({ saturation, selectionProbability }: { saturation: number; selectionProbability: string }) => (
<Card variant="outlined" sx={{ p: 1 }}>
<CardContent>
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight="medium">Stake saturation</Typography>
<Typography>{saturation}%</Typography>
</Stack>
<Divider sx={{ my: 1 }} />
<Stack direction="row" justifyContent="space-between">
<Typography fontWeight="medium">Selection probability</Typography>
<Typography>{selectionProbability}</Typography>
</Stack>
</CardContent>
</Card>
);
export const ApyPlayground = () => {
const [inputValues, setInputValues] = useState([
{ label: 'Profit margin', isPercentage: true, value: '' },
{ label: 'Operator cost', value: '' },
{ label: 'Bond', value: '' },
{ label: 'Delegations', value: '' },
{ label: 'Uptime', isPercentage: true, value: '' },
]);
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setInputValues((current) => [
...current.map((input) => (input.label === e.target.name ? { ...input, value: e.target.value } : input)),
]);
};
const handleCalculate = () => console.log(inputValues);
return (
<Box sx={{ p: 3 }}>
<Typography fontWeight="medium" sx={{ mb: 1 }}>
Playground
</Typography>
<Typography variant="body2" sx={{ color: 'grey.600', mb: 2 }}>
This is your parameters playground - change the parameters below to see the node specific estimations in the
table
</Typography>
<Card variant="outlined" sx={{ p: 1, mb: 3 }}>
<CardHeader
title={
<Typography variant="body2" fontWeight="medium">
Estimation calculator
</Typography>
}
/>
<CardContent>
<Grid container spacing={3} alignItems="center">
{inputValues.map((input) => (
<Grid item xs={12} lg={2}>
<TextField
fullWidth
label={input.label}
name={input.label}
value={input.value}
onChange={handleInputChange}
InputProps={{
endAdornment: (
<Typography sx={{ color: 'grey.600' }}>{input.isPercentage ? '%' : 'NYM'}</Typography>
),
}}
/>
</Grid>
))}
<Grid item xs={12} lg={2}>
<Button variant="contained" disableElevation onClick={handleCalculate} size="large" fullWidth>
Calculate
</Button>
</Grid>
</Grid>
</CardContent>
</Card>
<Grid container spacing={3}>
<Grid item xs={12} md={8}>
<ResultsTable />
</Grid>
<Grid item xs={12} md={4}>
<NodeDetails saturation={10} selectionProbability="Low" />
</Grid>
</Grid>
</Box>
);
};
+1
View File
@@ -84,6 +84,7 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
].join(','),
fontSize: 14,
fontWeightRegular: 500,
fontWeightMedium: 600,
button: {
textTransform: 'none',
fontWeight: '600',