Add popovers with descriptions for each single parameter
This commit is contained in:
parent
1c993642af
commit
cce04ea80e
148
src/App.tsx
148
src/App.tsx
|
|
@ -15,6 +15,12 @@ import SupplyVsDemandChart from "./SupplyVsDemandChart";
|
|||
import ResultParams from "./ResultParams";
|
||||
import PriceSimulationChart from "./PriceSimulationChart";
|
||||
import HelpText from "./HelpText";
|
||||
// Text content
|
||||
import {
|
||||
parameterDescriptions,
|
||||
simulationParameterDescriptions,
|
||||
resultParameterDescriptions
|
||||
} from "./parametersDescriptions";
|
||||
// Utils
|
||||
import { getLast, getAvg, pause } from "./utils";
|
||||
import {
|
||||
|
|
@ -122,11 +128,10 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||
}
|
||||
},
|
||||
descriptionTitle: {
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
padding: theme.spacing(0.5)
|
||||
},
|
||||
descriptionName: {
|
||||
fontWeight: theme.typography.fontWeightBold
|
||||
descriptionBody: {
|
||||
color: "#dbdfe4"
|
||||
},
|
||||
descriptionPadding: {
|
||||
padding: theme.spacing(0.5)
|
||||
|
|
@ -134,73 +139,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
|||
})
|
||||
);
|
||||
|
||||
const parameterDescriptions = [
|
||||
{
|
||||
name: "Initial raise",
|
||||
text: "Total funds raised in the hatch period of the ABC launch"
|
||||
},
|
||||
{
|
||||
name: "Allocation to funding pool",
|
||||
text:
|
||||
"The percentage of the funds raised in the Hatch sale that go directly into the project funding pool to compensate future work done in the project"
|
||||
},
|
||||
{
|
||||
name: "Hatch price",
|
||||
text:
|
||||
"The price paid per 'ABC token' by community members involved in hatching the project"
|
||||
},
|
||||
{
|
||||
name: "Post-hatch price",
|
||||
text:
|
||||
"The price of the 'ABC token' when the curve enters the open phase and is live for public participation"
|
||||
},
|
||||
{
|
||||
name: "Exit tribute",
|
||||
text:
|
||||
"The percentage of funds that are diverted to the project funding pool from community members who exit funds from the project by burning 'ABC tokens' in exchange for collateral"
|
||||
}
|
||||
];
|
||||
|
||||
const simulationParameterDescriptions = [
|
||||
{
|
||||
name: "Price",
|
||||
text: "Price of the token over time."
|
||||
},
|
||||
{
|
||||
name: "Floor price",
|
||||
text:
|
||||
"Lower bound of the price guaranteed by the vesting of hatch tokens. It decreases over time as more hatch tokens are allowed to be traded"
|
||||
},
|
||||
{
|
||||
name: "Total exit tributes",
|
||||
text:
|
||||
"Cumulative sum of exit tributes collected from only exit /sell transactions"
|
||||
}
|
||||
];
|
||||
|
||||
const resultParameterDescriptions = [
|
||||
{
|
||||
name: "Total reserve",
|
||||
text:
|
||||
"Total DAI in the smart contract reserve at the end of the simulated period"
|
||||
},
|
||||
{
|
||||
name: "Funds generated from initial hatch",
|
||||
text:
|
||||
"Fraction of the funds (theta) raised during the hatch that go directly to the cause (analytic result)"
|
||||
},
|
||||
{
|
||||
name: "Funds generated from exit tributes",
|
||||
text:
|
||||
"Cumulative sum of exit tributes collected from only exit /sell transactions"
|
||||
},
|
||||
{
|
||||
name: "Average slippage",
|
||||
text:
|
||||
"Average of the slippage of each transaction occured during the simulation period"
|
||||
}
|
||||
];
|
||||
|
||||
export default function App() {
|
||||
const [curveParams, setCurveParams] = useState({
|
||||
theta: 0.35, // fraction allocated to reserve (.)
|
||||
|
|
@ -386,14 +324,17 @@ export default function App() {
|
|||
const resultFields = [
|
||||
{
|
||||
label: `Total reserve`,
|
||||
description: resultParameterDescriptions.totalReserve.text,
|
||||
value: (+totalReserve.toPrecision(3)).toLocaleString() + " DAI"
|
||||
},
|
||||
{
|
||||
label: `Funds generated from initial hatch`,
|
||||
description: resultParameterDescriptions.initialHatchFunds.text,
|
||||
value: Math.round(d0 * theta).toLocaleString() + " DAI"
|
||||
},
|
||||
{
|
||||
label: `Funds generated from exit tributes (${withdrawCount} txs)`,
|
||||
description: resultParameterDescriptions.exitTributes.text,
|
||||
value:
|
||||
(+getLast(withdrawFeeTimeseries).toPrecision(3)).toLocaleString() +
|
||||
" DAI"
|
||||
|
|
@ -402,6 +343,7 @@ export default function App() {
|
|||
label: `Average slippage (avg tx size ${Math.round(
|
||||
avgTxSize
|
||||
).toLocaleString()} DAI)`,
|
||||
description: resultParameterDescriptions.slippage.text,
|
||||
value: +(100 * avgSlippage).toFixed(3) + "%"
|
||||
}
|
||||
];
|
||||
|
|
@ -432,15 +374,21 @@ export default function App() {
|
|||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
{parameterDescriptions.map(({ name, text }) => (
|
||||
{[
|
||||
parameterDescriptions.theta,
|
||||
parameterDescriptions.p0,
|
||||
parameterDescriptions.p1,
|
||||
parameterDescriptions.wFee,
|
||||
parameterDescriptions.d0
|
||||
].map(({ name, text }) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<Typography className={classes.descriptionName}>
|
||||
{name}
|
||||
</Typography>
|
||||
<Typography>{name}</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Typography>{text}</Typography>
|
||||
<Typography className={classes.descriptionBody}>
|
||||
{text}
|
||||
</Typography>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
|
|
@ -478,7 +426,7 @@ export default function App() {
|
|||
<HelpText
|
||||
text={
|
||||
<div className={classes.descriptionPadding}>
|
||||
<Typography>
|
||||
<Typography className={classes.descriptionBody}>
|
||||
Visualization of the token bonding curve analytic
|
||||
function on a specific range of reserve [0, 4 * R0].
|
||||
This result is deterministic given the current set of
|
||||
|
|
@ -533,7 +481,7 @@ export default function App() {
|
|||
text={
|
||||
<div className={classes.descriptionContainer}>
|
||||
<div className={classes.descriptionPadding}>
|
||||
<Typography>
|
||||
<Typography className={classes.descriptionBody}>
|
||||
This chart shows a 52 week simulation of discrete
|
||||
transactions interacting with the token bonding
|
||||
curve. Each transaction adds or substract reserve
|
||||
|
|
@ -546,22 +494,22 @@ export default function App() {
|
|||
|
||||
<table>
|
||||
<tbody>
|
||||
{simulationParameterDescriptions.map(
|
||||
({ name, text }) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<Typography
|
||||
className={classes.descriptionName}
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Typography>{text}</Typography>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
{Object.values(
|
||||
simulationParameterDescriptions
|
||||
).map(({ name, text }) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<Typography>{name}</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Typography
|
||||
className={classes.descriptionBody}
|
||||
>
|
||||
{text}
|
||||
</Typography>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -595,18 +543,18 @@ export default function App() {
|
|||
</div>
|
||||
<table>
|
||||
<tbody>
|
||||
{resultParameterDescriptions.map(
|
||||
{Object.values(resultParameterDescriptions).map(
|
||||
({ name, text }) => (
|
||||
<tr key={name}>
|
||||
<td>
|
||||
<Typography
|
||||
className={classes.descriptionName}
|
||||
>
|
||||
{name}
|
||||
</Typography>
|
||||
<Typography>{name}</Typography>
|
||||
</td>
|
||||
<td>
|
||||
<Typography>{text}</Typography>
|
||||
<Typography
|
||||
className={classes.descriptionBody}
|
||||
>
|
||||
{text}
|
||||
</Typography>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { InputFieldInterface, CurveParamsInterface } from "./types";
|
||||
import InputParams from "./InputParams";
|
||||
import { parameterDescriptions } from "./parametersDescriptions";
|
||||
|
||||
export default function CurveDesignInputParams({
|
||||
curveParams,
|
||||
|
|
@ -42,6 +43,7 @@ export default function CurveDesignInputParams({
|
|||
const inputFields: InputFieldInterface[] = [
|
||||
{
|
||||
label: "Allocation to funding pool",
|
||||
description: parameterDescriptions.theta.text,
|
||||
value: theta,
|
||||
setter: setTheta,
|
||||
min: 0,
|
||||
|
|
@ -54,6 +56,7 @@ export default function CurveDesignInputParams({
|
|||
},
|
||||
{
|
||||
label: "Hatch price (DAI/token)",
|
||||
description: parameterDescriptions.p0.text,
|
||||
value: p0,
|
||||
setter: _setP0,
|
||||
min: 0.01,
|
||||
|
|
@ -65,6 +68,7 @@ export default function CurveDesignInputParams({
|
|||
},
|
||||
{
|
||||
label: "Post-hatch price (DAI/token)",
|
||||
description: parameterDescriptions.p1.text,
|
||||
value: p1,
|
||||
setter: setP1,
|
||||
min: p0 || 0.1,
|
||||
|
|
@ -76,6 +80,7 @@ export default function CurveDesignInputParams({
|
|||
},
|
||||
{
|
||||
label: "Exit tribute",
|
||||
description: parameterDescriptions.wFee.text,
|
||||
value: wFee,
|
||||
setter: setWFee,
|
||||
min: 0,
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import React from "react";
|
||||
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import TextField from "@material-ui/core/TextField";
|
||||
import NumberFormat from "react-number-format";
|
||||
import { InputFieldInterface } from "./types";
|
||||
import PrettoSlider from "./PrettoSlider";
|
||||
import TextWithPopover from "./TextWithPopover";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
|
|
@ -81,6 +81,7 @@ export default function InputParams({
|
|||
{inputFields.map(
|
||||
({
|
||||
label,
|
||||
description,
|
||||
value,
|
||||
setter,
|
||||
min,
|
||||
|
|
@ -103,9 +104,7 @@ export default function InputParams({
|
|||
return (
|
||||
<Grid key={label} container spacing={0} className={classes.listBox}>
|
||||
<Grid item xs={6} className={classes.leftContainer}>
|
||||
<Typography id={label} gutterBottom>
|
||||
{label}
|
||||
</Typography>
|
||||
<TextWithPopover content={label} popoverText={description} />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={2} className={classes.centerContainer}>
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import React from "react";
|
|||
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Grid from "@material-ui/core/Grid";
|
||||
import TextWithPopover from "./TextWithPopover";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
|
|
@ -45,6 +46,7 @@ export default function ResultParams({
|
|||
}: {
|
||||
resultFields: {
|
||||
label: string;
|
||||
description: string;
|
||||
value: number | string;
|
||||
}[];
|
||||
}) {
|
||||
|
|
@ -52,12 +54,10 @@ export default function ResultParams({
|
|||
|
||||
return (
|
||||
<div className={classes.listBoxContainer}>
|
||||
{resultFields.map(({ label, value }) => (
|
||||
{resultFields.map(({ label, description, value }) => (
|
||||
<Grid key={label} container spacing={0} className={classes.listBox}>
|
||||
<Grid item xs={8} className={classes.leftContainer}>
|
||||
<Typography id={label} gutterBottom>
|
||||
{label}
|
||||
</Typography>
|
||||
<TextWithPopover content={label} popoverText={description} />
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={4} className={classes.centerContainer}>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { InputFieldInterface, CurveParamsInterface } from "./types";
|
||||
import InputParams from "./InputParams";
|
||||
import { parameterDescriptions } from "./parametersDescriptions";
|
||||
|
||||
export default function CurveDesignInputParams({
|
||||
curveParams,
|
||||
|
|
@ -25,6 +26,7 @@ export default function CurveDesignInputParams({
|
|||
const inputFields: InputFieldInterface[] = [
|
||||
{
|
||||
label: "Initial raise (DAI)",
|
||||
description: parameterDescriptions.d0.text,
|
||||
value: d0,
|
||||
setter: setD0,
|
||||
min: 0.1e6,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
import React from "react";
|
||||
import { makeStyles } from "@material-ui/core/styles";
|
||||
import Popover from "@material-ui/core/Popover";
|
||||
import Typography from "@material-ui/core/Typography";
|
||||
import Box from "@material-ui/core/Box";
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
container: {
|
||||
color: theme.palette.text.secondary,
|
||||
display: "flex",
|
||||
marginLeft: "6px",
|
||||
fontSize: "0.9rem",
|
||||
cursor: "pointer",
|
||||
transition: "color ease 150ms",
|
||||
"&:hover": {
|
||||
color: "#c3c9d0"
|
||||
}
|
||||
},
|
||||
popoverContainer: {
|
||||
padding: theme.spacing(2),
|
||||
"& > p:not(:last-child)": {
|
||||
paddingBottom: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1),
|
||||
borderBottom: "1px solid #3f5463"
|
||||
}
|
||||
},
|
||||
paper: {
|
||||
backgroundColor: "#384b59",
|
||||
maxWidth: theme.breakpoints.values.md * 0.9,
|
||||
[`@media screen and (max-width: ${theme.breakpoints.values.md}px)`]: {
|
||||
maxWidth: "90vw"
|
||||
},
|
||||
padding: theme.spacing(0.5)
|
||||
},
|
||||
descriptionBody: {
|
||||
color: "#dbdfe4"
|
||||
}
|
||||
}));
|
||||
|
||||
export default function TextWithPopover({
|
||||
content,
|
||||
popoverText
|
||||
}: {
|
||||
content: string;
|
||||
popoverText: string;
|
||||
}) {
|
||||
const classes = useStyles();
|
||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||
|
||||
function handleClick(event: any) {
|
||||
setAnchorEl(event.currentTarget);
|
||||
}
|
||||
|
||||
function handleClose() {
|
||||
setAnchorEl(null);
|
||||
}
|
||||
|
||||
const open = Boolean(anchorEl);
|
||||
const id = open ? "simple-popover" : undefined;
|
||||
|
||||
return (
|
||||
<div className={classes.container}>
|
||||
<div aria-describedby={id} onClick={handleClick}>
|
||||
<Typography gutterBottom>{content}</Typography>
|
||||
</div>
|
||||
<Popover
|
||||
PaperProps={{
|
||||
className: classes.paper
|
||||
}}
|
||||
id={id}
|
||||
open={open}
|
||||
anchorEl={anchorEl}
|
||||
onClose={handleClose}
|
||||
onClick={handleClose}
|
||||
anchorOrigin={{
|
||||
vertical: "bottom",
|
||||
horizontal: "center"
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: "top",
|
||||
horizontal: "center"
|
||||
}}
|
||||
>
|
||||
<Box className={classes.popoverContainer}>
|
||||
<Typography>{content}</Typography>
|
||||
<Typography className={classes.descriptionBody}>
|
||||
{popoverText}
|
||||
</Typography>
|
||||
</Box>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
export interface DescriptionObject {
|
||||
[key: string]: { name: string; text: string };
|
||||
}
|
||||
|
||||
export const parameterDescriptions: DescriptionObject = {
|
||||
theta: {
|
||||
name: "Allocation to funding pool",
|
||||
text:
|
||||
"The percentage of the funds raised in the Hatch sale that go directly into the project funding pool to compensate future work done in the project"
|
||||
},
|
||||
p0: {
|
||||
name: "Hatch price",
|
||||
text:
|
||||
"The price paid per 'ABC token' by community members involved in hatching the project"
|
||||
},
|
||||
p1: {
|
||||
name: "Post-hatch price",
|
||||
text:
|
||||
"The price of the 'ABC token' when the curve enters the open phase and is live for public participation"
|
||||
},
|
||||
wFee: {
|
||||
name: "Exit tribute",
|
||||
text:
|
||||
"The percentage of funds that are diverted to the project funding pool from community members who exit funds from the project by burning 'ABC tokens' in exchange for collateral"
|
||||
},
|
||||
d0: {
|
||||
name: "Initial raise",
|
||||
text: "Total funds raised in the hatch period of the ABC launch"
|
||||
}
|
||||
};
|
||||
|
||||
export const simulationParameterDescriptions: DescriptionObject = {
|
||||
price: {
|
||||
name: "Price",
|
||||
text: "Price of the token over time."
|
||||
},
|
||||
floorPrice: {
|
||||
name: "Floor price",
|
||||
text:
|
||||
"Lower bound of the price guaranteed by the vesting of hatch tokens. It decreases over time as more hatch tokens are allowed to be traded"
|
||||
},
|
||||
exitTributes: {
|
||||
name: "Total exit tributes",
|
||||
text:
|
||||
"Cumulative sum of exit tributes collected from only exit /sell transactions"
|
||||
}
|
||||
};
|
||||
|
||||
export const resultParameterDescriptions: DescriptionObject = {
|
||||
totalReserve: {
|
||||
name: "Total reserve",
|
||||
text:
|
||||
"Total DAI in the smart contract reserve at the end of the simulated period"
|
||||
},
|
||||
initialHatchFunds: {
|
||||
name: "Funds generated from initial hatch",
|
||||
text:
|
||||
"Fraction of the funds (theta) raised during the hatch that go directly to the cause (analytic result)"
|
||||
},
|
||||
exitTributes: {
|
||||
name: "Funds generated from exit tributes",
|
||||
text: simulationParameterDescriptions.exitTributes.text
|
||||
},
|
||||
slippage: {
|
||||
name: "Average slippage",
|
||||
text:
|
||||
"Average of the slippage of each transaction occured during the simulation period"
|
||||
}
|
||||
};
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
export interface InputFieldInterface {
|
||||
label: string;
|
||||
description: string;
|
||||
value: number;
|
||||
setter(newValue: any): void;
|
||||
min: number;
|
||||
|
|
|
|||
Loading…
Reference in New Issue