apy playground ui
update calc button style validator-api-client and wallet: compute mixnode reward estimation
This commit is contained in:
@@ -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";
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -84,6 +84,7 @@ export const getDesignTokens = (mode: PaletteMode): ThemeOptions => {
|
||||
].join(','),
|
||||
fontSize: 14,
|
||||
fontWeightRegular: 500,
|
||||
fontWeightMedium: 600,
|
||||
button: {
|
||||
textTransform: 'none',
|
||||
fontWeight: '600',
|
||||
|
||||
Reference in New Issue
Block a user