Add vesting life slider + make initial raise slider bigger
This commit is contained in:
parent
0696188191
commit
5ce3706232
167
src/App.tsx
167
src/App.tsx
|
|
@ -115,7 +115,8 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
},
|
},
|
||||||
button: {
|
button: {
|
||||||
// background: "linear-gradient(290deg, #2ad179, #4ab47c)", // Green gradient
|
// background: "linear-gradient(290deg, #2ad179, #4ab47c)", // Green gradient
|
||||||
background: "linear-gradient(290deg, #1880e0, #3873d8)", // blue gradient
|
background: "linear-gradient(290deg, #1aa059, #3d9567)", // Darker Green gradient
|
||||||
|
// background: "linear-gradient(290deg, #1880e0, #3873d8)", // blue gradient
|
||||||
color: "white"
|
color: "white"
|
||||||
},
|
},
|
||||||
// Descriptions
|
// Descriptions
|
||||||
|
|
@ -138,6 +139,23 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
},
|
},
|
||||||
descriptionPadding: {
|
descriptionPadding: {
|
||||||
padding: theme.spacing(0.5)
|
padding: theme.spacing(0.5)
|
||||||
|
},
|
||||||
|
d0Container: {
|
||||||
|
"& > div": {
|
||||||
|
padding: "0 12px 0 0 !important",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
d0Number: {
|
||||||
|
padding: "0 !important",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center"
|
||||||
|
},
|
||||||
|
d0Slidder: {
|
||||||
|
padding: "0 12px 0 0 !important",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -148,10 +166,11 @@ export default function App() {
|
||||||
p0: 0.1, // Hatch sale price p0 (DAI / token)
|
p0: 0.1, // Hatch sale price p0 (DAI / token)
|
||||||
p1: 0.3, // Return factor (.)
|
p1: 0.3, // Return factor (.)
|
||||||
wFee: 0.05, // friction coefficient (.)
|
wFee: 0.05, // friction coefficient (.)
|
||||||
|
vHalflife: 52, // Vesting half life (weeks)
|
||||||
d0: 3e6 // Initial raise, d0 (DAI)
|
d0: 3e6 // Initial raise, d0 (DAI)
|
||||||
});
|
});
|
||||||
|
|
||||||
const { d0, theta, p0, p1, wFee } = curveParams;
|
const { d0, theta, p0, p1, wFee, vHalflife } = curveParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Throttle the curve update to prevent the expensive chart
|
* Throttle the curve update to prevent the expensive chart
|
||||||
|
|
@ -233,7 +252,7 @@ export default function App() {
|
||||||
const tx_spread = 10;
|
const tx_spread = 10;
|
||||||
// vesting(should this be exposed in the app ?)
|
// vesting(should this be exposed in the app ?)
|
||||||
const cliff = 8; // weeks before vesting starts ~2 months
|
const cliff = 8; // weeks before vesting starts ~2 months
|
||||||
const halflife = 52; // 26 weeks, half life is ~6 months
|
// const halflife = 52; // 26 weeks, half life is ~6 months
|
||||||
// percentage of the hatch tokens which vest per week(since that is our timescale in the sim)
|
// percentage of the hatch tokens which vest per week(since that is our timescale in the sim)
|
||||||
|
|
||||||
// numSteps = 52 take 8ms to run
|
// numSteps = 52 take 8ms to run
|
||||||
|
|
@ -275,7 +294,7 @@ export default function App() {
|
||||||
// txsWithdraw.reduce((t, c) => t + c, 0);
|
// txsWithdraw.reduce((t, c) => t + c, 0);
|
||||||
|
|
||||||
// Vest
|
// Vest
|
||||||
const delta_H = vest_tokens({ week: t, H, halflife, cliff });
|
const delta_H = vest_tokens({ week: t, H, halflife: vHalflife, cliff });
|
||||||
const H_next = H - delta_H;
|
const H_next = H - delta_H;
|
||||||
|
|
||||||
// find floor price
|
// find floor price
|
||||||
|
|
@ -346,14 +365,14 @@ export default function App() {
|
||||||
description: resultParameterDescriptions.exitTributes.text,
|
description: resultParameterDescriptions.exitTributes.text,
|
||||||
value:
|
value:
|
||||||
(+getLast(withdrawFeeTimeseries).toPrecision(3)).toLocaleString() +
|
(+getLast(withdrawFeeTimeseries).toPrecision(3)).toLocaleString() +
|
||||||
` DAI (${withdrawCount} txs)`
|
" DAI",
|
||||||
|
valueFooter: `From ${withdrawCount} exit txs`
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: resultParameterDescriptions.slippage.name,
|
label: resultParameterDescriptions.slippage.name,
|
||||||
description: resultParameterDescriptions.slippage.text,
|
description: resultParameterDescriptions.slippage.text,
|
||||||
value:
|
value: +(100 * avgSlippage).toFixed(3) + " %",
|
||||||
+(100 * avgSlippage).toFixed(3) +
|
valueFooter: `Avg tx size ${Math.round(avgTxSize).toLocaleString()} DAI`
|
||||||
` % (avg tx size ${Math.round(avgTxSize).toLocaleString()} DAI)`
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
@ -374,37 +393,14 @@ export default function App() {
|
||||||
<Box className={classes.boxHeader}>
|
<Box className={classes.boxHeader}>
|
||||||
<Typography variant="h6">Curve Design</Typography>
|
<Typography variant="h6">Curve Design</Typography>
|
||||||
<HelpText
|
<HelpText
|
||||||
text={
|
title={"Parameters description"}
|
||||||
<div className={classes.descriptionContainer}>
|
table={[
|
||||||
<div>
|
parameterDescriptions.theta,
|
||||||
<Typography className={classes.descriptionTitle}>
|
parameterDescriptions.p0,
|
||||||
Parameters description:
|
parameterDescriptions.p1,
|
||||||
</Typography>
|
parameterDescriptions.wFee,
|
||||||
</div>
|
parameterDescriptions.vHalflife
|
||||||
<table>
|
]}
|
||||||
<tbody>
|
|
||||||
{[
|
|
||||||
parameterDescriptions.theta,
|
|
||||||
parameterDescriptions.p0,
|
|
||||||
parameterDescriptions.p1,
|
|
||||||
parameterDescriptions.wFee,
|
|
||||||
parameterDescriptions.d0
|
|
||||||
].map(({ name, text }) => (
|
|
||||||
<tr key={name}>
|
|
||||||
<td>
|
|
||||||
<Typography>{name}</Typography>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Typography className={classes.descriptionBody}>
|
|
||||||
{text}
|
|
||||||
</Typography>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
))}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
@ -414,17 +410,6 @@ export default function App() {
|
||||||
setCurveParams={setCurveParamsThrottle}
|
setCurveParams={setCurveParamsThrottle}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className={`${classes.boxHeader} ${classes.initialRaise}`}>
|
|
||||||
<Typography variant="h6">Run parameters</Typography>
|
|
||||||
</Box>
|
|
||||||
|
|
||||||
<Box className={classes.box}>
|
|
||||||
<SimulationInputParams
|
|
||||||
curveParams={curveParams}
|
|
||||||
setCurveParams={setCurveParamsThrottle}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
</Paper>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
|
|
@ -432,15 +417,7 @@ export default function App() {
|
||||||
<Paper className={classes.paper}>
|
<Paper className={classes.paper}>
|
||||||
<Box className={classes.boxHeader}>
|
<Box className={classes.boxHeader}>
|
||||||
<Typography variant="h6">Preview</Typography>
|
<Typography variant="h6">Preview</Typography>
|
||||||
<HelpText
|
<HelpText body={supplyVsDemandChartDescription} />
|
||||||
text={
|
|
||||||
<div className={classes.descriptionPadding}>
|
|
||||||
<Typography className={classes.descriptionBody}>
|
|
||||||
{supplyVsDemandChartDescription}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box className={classes.boxChart}>
|
<Box className={classes.boxChart}>
|
||||||
|
|
@ -451,8 +428,15 @@ export default function App() {
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid container spacing={3}>
|
<Grid container spacing={3}>
|
||||||
<Grid item xs={12} md={12}>
|
<Grid item xs={12}>
|
||||||
<Paper>
|
<Paper>
|
||||||
|
<Box className={`${classes.box} ${classes.boxBorderBottom}`}>
|
||||||
|
<SimulationInputParams
|
||||||
|
curveParams={curveParams}
|
||||||
|
setCurveParams={setCurveParamsThrottle}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Box className={classes.boxHeader}>
|
<Box className={classes.boxHeader}>
|
||||||
<Grid
|
<Grid
|
||||||
container
|
container
|
||||||
|
|
@ -482,36 +466,8 @@ export default function App() {
|
||||||
<Box className={classes.boxHeader}>
|
<Box className={classes.boxHeader}>
|
||||||
<Typography variant="h6">Simulation</Typography>
|
<Typography variant="h6">Simulation</Typography>
|
||||||
<HelpText
|
<HelpText
|
||||||
text={
|
body={simulationChartDescription}
|
||||||
<div className={classes.descriptionContainer}>
|
table={Object.values(simulationParameterDescriptions)}
|
||||||
<div className={classes.descriptionPadding}>
|
|
||||||
<Typography className={classes.descriptionBody}>
|
|
||||||
{simulationChartDescription}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
{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>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
@ -533,35 +489,8 @@ export default function App() {
|
||||||
<Box className={classes.boxHeader}>
|
<Box className={classes.boxHeader}>
|
||||||
<Typography variant="h6">Results</Typography>
|
<Typography variant="h6">Results</Typography>
|
||||||
<HelpText
|
<HelpText
|
||||||
text={
|
title={"Result parameters description"}
|
||||||
<div className={classes.descriptionContainer}>
|
table={Object.values(resultParameterDescriptions)}
|
||||||
<div>
|
|
||||||
<Typography className={classes.descriptionTitle}>
|
|
||||||
Result parameters description:
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<table>
|
|
||||||
<tbody>
|
|
||||||
{Object.values(resultParameterDescriptions).map(
|
|
||||||
({ name, text }) => (
|
|
||||||
<tr key={name}>
|
|
||||||
<td>
|
|
||||||
<Typography>{name}</Typography>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<Typography
|
|
||||||
className={classes.descriptionBody}
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</Typography>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,12 +14,14 @@ export default function CurveDesignInputParams({
|
||||||
const [p0, setP0] = useState(0.1); // Hatch sale Price p0 (DAI / token)
|
const [p0, setP0] = useState(0.1); // Hatch sale Price p0 (DAI / token)
|
||||||
const [p1, setP1] = useState(0.3); // Return factor (.)
|
const [p1, setP1] = useState(0.3); // Return factor (.)
|
||||||
const [wFee, setWFee] = useState(0.05); // friction coefficient (.)
|
const [wFee, setWFee] = useState(0.05); // friction coefficient (.)
|
||||||
|
const [vHalflife, setVHalflife] = useState(52); // friction coefficient (.)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTheta(curveParams.theta);
|
setTheta(curveParams.theta);
|
||||||
setP0(curveParams.p0);
|
setP0(curveParams.p0);
|
||||||
setP1(curveParams.p1);
|
setP1(curveParams.p1);
|
||||||
setWFee(curveParams.wFee);
|
setWFee(curveParams.wFee);
|
||||||
|
setVHalflife(curveParams.vHalflife);
|
||||||
}, [curveParams]);
|
}, [curveParams]);
|
||||||
|
|
||||||
function _setP0(newP0: number) {
|
function _setP0(newP0: number) {
|
||||||
|
|
@ -34,7 +36,8 @@ export default function CurveDesignInputParams({
|
||||||
theta,
|
theta,
|
||||||
p0,
|
p0,
|
||||||
p1,
|
p1,
|
||||||
wFee
|
wFee,
|
||||||
|
vHalflife
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -90,6 +93,19 @@ export default function CurveDesignInputParams({
|
||||||
format: (n: number) => `${+(100 * n).toFixed(1)}%`,
|
format: (n: number) => `${+(100 * n).toFixed(1)}%`,
|
||||||
toText: (n: number) => String(+(n * 1e2).toFixed(1)),
|
toText: (n: number) => String(+(n * 1e2).toFixed(1)),
|
||||||
toNum: (n: string) => parseFloat(n) * 1e-2
|
toNum: (n: string) => parseFloat(n) * 1e-2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: `${parameterDescriptions.vHalflife.name} (weeks)`,
|
||||||
|
description: parameterDescriptions.vHalflife.text,
|
||||||
|
value: vHalflife,
|
||||||
|
setter: setVHalflife,
|
||||||
|
min: 52 / 2,
|
||||||
|
max: 52 * 2,
|
||||||
|
step: 1,
|
||||||
|
suffix: "",
|
||||||
|
format: (n: number) => String(Math.round(n)),
|
||||||
|
toText: (n: number) => String(Math.round(n)),
|
||||||
|
toNum: (n: string) => Math.round(parseInt(n))
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import Popover from "@material-ui/core/Popover";
|
import Popover from "@material-ui/core/Popover";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
import Box from "@material-ui/core/Box";
|
import Box from "@material-ui/core/Box";
|
||||||
import HelpIcon from "@material-ui/icons/HelpOutline";
|
import HelpIcon from "@material-ui/icons/HelpOutline";
|
||||||
|
|
||||||
|
|
@ -25,10 +26,42 @@ const useStyles = makeStyles(theme => ({
|
||||||
[`@media screen and (max-width: ${theme.breakpoints.values.md}px)`]: {
|
[`@media screen and (max-width: ${theme.breakpoints.values.md}px)`]: {
|
||||||
maxWidth: "90vw"
|
maxWidth: "90vw"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
// Descriptions
|
||||||
|
descriptionContainer: {
|
||||||
|
"& > div:not(:last-child)": {
|
||||||
|
paddingBottom: theme.spacing(1),
|
||||||
|
marginBottom: theme.spacing(1),
|
||||||
|
borderBottom: "1px solid #3f5463"
|
||||||
|
},
|
||||||
|
"& td": {
|
||||||
|
verticalAlign: "top",
|
||||||
|
padding: theme.spacing(0.5)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
descriptionTitle: {
|
||||||
|
padding: theme.spacing(0.5)
|
||||||
|
},
|
||||||
|
descriptionBody: {
|
||||||
|
color: "#dbdfe4",
|
||||||
|
padding: theme.spacing(0.5)
|
||||||
|
},
|
||||||
|
descriptionPadding: {
|
||||||
|
padding: theme.spacing(0.5)
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export default function SimplePopover({ text }: { text: any }) {
|
export default function SimplePopover({
|
||||||
|
text,
|
||||||
|
title,
|
||||||
|
table,
|
||||||
|
body
|
||||||
|
}: {
|
||||||
|
text?: any;
|
||||||
|
title?: string;
|
||||||
|
table?: { name: string; text: string }[];
|
||||||
|
body?: string;
|
||||||
|
}) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const [anchorEl, setAnchorEl] = React.useState(null);
|
const [anchorEl, setAnchorEl] = React.useState(null);
|
||||||
|
|
||||||
|
|
@ -65,7 +98,48 @@ export default function SimplePopover({ text }: { text: any }) {
|
||||||
horizontal: "center"
|
horizontal: "center"
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box className={classes.popoverContainer}>{text}</Box>
|
<Box className={classes.popoverContainer}>
|
||||||
|
<div className={classes.descriptionContainer}>
|
||||||
|
{title && (
|
||||||
|
<div>
|
||||||
|
<Typography className={classes.descriptionTitle}>
|
||||||
|
{title}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{body && (
|
||||||
|
<div>
|
||||||
|
<Typography className={classes.descriptionBody}>
|
||||||
|
{body}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{table && (
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
{table.map(({ name, text }) => (
|
||||||
|
<tr key={name}>
|
||||||
|
<td>
|
||||||
|
<Typography>{name}</Typography>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<Typography className={classes.descriptionBody}>
|
||||||
|
{text}
|
||||||
|
</Typography>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{text}
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
</Popover>
|
</Popover>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
import React from "react";
|
||||||
|
import { createStyles, makeStyles, Theme } from "@material-ui/core/styles";
|
||||||
|
import Grid from "@material-ui/core/Grid";
|
||||||
|
import TextField from "@material-ui/core/TextField";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import NumberFormat from "react-number-format";
|
||||||
|
import { InputFieldInterface } from "./types";
|
||||||
|
import PrettoSlider from "./PrettoSlider";
|
||||||
|
import HelpText from "./HelpText";
|
||||||
|
|
||||||
|
const useStyles = makeStyles((theme: Theme) =>
|
||||||
|
createStyles({
|
||||||
|
root: {
|
||||||
|
margin: theme.spacing(6, 0, 3)
|
||||||
|
},
|
||||||
|
lightBulb: {
|
||||||
|
verticalAlign: "middle",
|
||||||
|
marginRight: theme.spacing(1)
|
||||||
|
},
|
||||||
|
leftContainer: {
|
||||||
|
// color: theme.palette.text.secondary
|
||||||
|
},
|
||||||
|
centerContainer: {
|
||||||
|
// color: blackColor
|
||||||
|
},
|
||||||
|
listBoxContainer: {
|
||||||
|
"& > div:not(:last-child)": {
|
||||||
|
paddingBottom: "12px",
|
||||||
|
marginBottom: "12px",
|
||||||
|
borderBottom: "1px solid #313d47"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
listBox: {
|
||||||
|
"& > div": {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
"& p": {
|
||||||
|
marginBottom: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"& > div:not(:last-child)": {
|
||||||
|
paddingRight: "12px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
slider: {
|
||||||
|
color: theme.palette.primary.main
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
function NumberFormatCustom(props: any) {
|
||||||
|
const { inputRef, onChange, prefix, suffix, ...other } = props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NumberFormat
|
||||||
|
{...other}
|
||||||
|
getInputRef={inputRef}
|
||||||
|
onValueChange={values => {
|
||||||
|
onChange({ target: { value: values.value } });
|
||||||
|
}}
|
||||||
|
thousandSeparator
|
||||||
|
prefix={prefix}
|
||||||
|
suffix={suffix}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function InputParamBig({
|
||||||
|
inputFields,
|
||||||
|
onChangeCommited
|
||||||
|
}: {
|
||||||
|
inputFields: InputFieldInterface[];
|
||||||
|
onChangeCommited(): void;
|
||||||
|
}) {
|
||||||
|
const classes = useStyles();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.listBoxContainer}>
|
||||||
|
{inputFields.map(
|
||||||
|
({
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
value,
|
||||||
|
setter,
|
||||||
|
min,
|
||||||
|
max,
|
||||||
|
step,
|
||||||
|
prefix,
|
||||||
|
suffix,
|
||||||
|
format,
|
||||||
|
toText,
|
||||||
|
toNum
|
||||||
|
}) => {
|
||||||
|
function sanitizeInput(num: number = 0) {
|
||||||
|
if (isNaN(num)) num = 0;
|
||||||
|
if (num > max) num = max;
|
||||||
|
else if (num < min) num = min;
|
||||||
|
setter(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid key={label} container spacing={0} className={classes.listBox}>
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={6}
|
||||||
|
sm={6}
|
||||||
|
md={3}
|
||||||
|
lg={2}
|
||||||
|
className={classes.leftContainer}
|
||||||
|
>
|
||||||
|
<Typography variant="h6">{label}</Typography>
|
||||||
|
<HelpText title={label} body={description} />
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
xs={2}
|
||||||
|
sm={2}
|
||||||
|
md={1}
|
||||||
|
className={classes.centerContainer}
|
||||||
|
>
|
||||||
|
<TextField
|
||||||
|
onChange={e => {
|
||||||
|
sanitizeInput(
|
||||||
|
toNum ? toNum(e.target.value) : parseFloat(e.target.value)
|
||||||
|
);
|
||||||
|
onChangeCommited();
|
||||||
|
}}
|
||||||
|
InputProps={{
|
||||||
|
inputComponent: NumberFormatCustom,
|
||||||
|
disableUnderline: true,
|
||||||
|
inputProps: {
|
||||||
|
prefix,
|
||||||
|
suffix
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={toText ? toText(value) : value}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
|
||||||
|
<Grid item xs={4} sm={4} md={8} lg={9}>
|
||||||
|
<PrettoSlider
|
||||||
|
className={classes.slider}
|
||||||
|
valueLabelDisplay="auto"
|
||||||
|
aria-label={label}
|
||||||
|
defaultValue={value}
|
||||||
|
onChange={(_, newValue) => sanitizeInput(Number(newValue))}
|
||||||
|
onChangeCommitted={onChangeCommited}
|
||||||
|
value={value}
|
||||||
|
min={min}
|
||||||
|
max={max}
|
||||||
|
step={step}
|
||||||
|
valueLabelFormat={value => format(value).replace("$", "")}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -43,9 +43,6 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
},
|
},
|
||||||
slider: {
|
slider: {
|
||||||
color: theme.palette.primary.main
|
color: theme.palette.primary.main
|
||||||
},
|
|
||||||
secondaryColor: {
|
|
||||||
color: theme.palette.secondary.light
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -89,7 +86,6 @@ export default function InputParams({
|
||||||
step,
|
step,
|
||||||
prefix,
|
prefix,
|
||||||
suffix,
|
suffix,
|
||||||
secondaryColor,
|
|
||||||
format,
|
format,
|
||||||
toText,
|
toText,
|
||||||
toNum
|
toNum
|
||||||
|
|
@ -108,7 +104,6 @@ export default function InputParams({
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={2} className={classes.centerContainer}>
|
<Grid item xs={2} className={classes.centerContainer}>
|
||||||
{/* <Typography gutterBottom>{display(value)}</Typography> */}
|
|
||||||
<TextField
|
<TextField
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
sanitizeInput(
|
sanitizeInput(
|
||||||
|
|
@ -130,9 +125,7 @@ export default function InputParams({
|
||||||
|
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<PrettoSlider
|
<PrettoSlider
|
||||||
className={`${classes.slider} ${
|
className={classes.slider}
|
||||||
secondaryColor ? classes.secondaryColor : ""
|
|
||||||
}`}
|
|
||||||
valueLabelDisplay="auto"
|
valueLabelDisplay="auto"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
defaultValue={value}
|
defaultValue={value}
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,10 @@ const useStyles = makeStyles((theme: Theme) =>
|
||||||
"& > div:not(:last-child)": {
|
"& > div:not(:last-child)": {
|
||||||
paddingRight: "12px"
|
paddingRight: "12px"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
valueFooter: {
|
||||||
|
color: theme.palette.text.secondary,
|
||||||
|
fontSize: "80%"
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
@ -50,6 +54,7 @@ export default function ResultParams({
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
value: number | string;
|
value: number | string;
|
||||||
|
valueFooter?: string;
|
||||||
}[];
|
}[];
|
||||||
simulationDuration: number;
|
simulationDuration: number;
|
||||||
}) {
|
}) {
|
||||||
|
|
@ -58,7 +63,7 @@ export default function ResultParams({
|
||||||
* Keep the animation active only during the initial animation time,
|
* Keep the animation active only during the initial animation time,
|
||||||
* but afterwards, deactivate to prevent the re-size ugly effect
|
* but afterwards, deactivate to prevent the re-size ugly effect
|
||||||
*/
|
*/
|
||||||
const [isAnimationActive, setIsAnimationActive] = useState(true);
|
const [isAnimationActive, setIsAnimationActive] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
setIsAnimationActive(false);
|
setIsAnimationActive(false);
|
||||||
|
|
@ -72,7 +77,7 @@ export default function ResultParams({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.listBoxContainer}>
|
<div className={classes.listBoxContainer}>
|
||||||
{resultFields.map(({ label, description, value }) => (
|
{resultFields.map(({ label, description, value, valueFooter }) => (
|
||||||
<Grid key={label} container spacing={0} className={classes.listBox}>
|
<Grid key={label} container spacing={0} className={classes.listBox}>
|
||||||
<Grid item xs={8} className={classes.leftContainer}>
|
<Grid item xs={8} className={classes.leftContainer}>
|
||||||
<TextWithPopover content={label} popoverText={description} />
|
<TextWithPopover content={label} popoverText={description} />
|
||||||
|
|
@ -82,7 +87,14 @@ export default function ResultParams({
|
||||||
{isAnimationActive ? (
|
{isAnimationActive ? (
|
||||||
<DotsLoader />
|
<DotsLoader />
|
||||||
) : (
|
) : (
|
||||||
<Typography gutterBottom>{value}</Typography>
|
<div>
|
||||||
|
<Typography>{value}</Typography>
|
||||||
|
{valueFooter && (
|
||||||
|
<Typography className={classes.valueFooter}>
|
||||||
|
{valueFooter}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { InputFieldInterface, CurveParamsInterface } from "./types";
|
import { InputFieldInterface, CurveParamsInterface } from "./types";
|
||||||
import InputParams from "./InputParams";
|
import InputParamBig from "./InputParamBig";
|
||||||
import { parameterDescriptions } from "./parametersDescriptions";
|
import { parameterDescriptions } from "./parametersDescriptions";
|
||||||
|
|
||||||
export default function CurveDesignInputParams({
|
export default function SimulationInputParams({
|
||||||
curveParams,
|
curveParams,
|
||||||
setCurveParams
|
setCurveParams
|
||||||
}: {
|
}: {
|
||||||
|
|
@ -25,7 +25,7 @@ export default function CurveDesignInputParams({
|
||||||
|
|
||||||
const inputFields: InputFieldInterface[] = [
|
const inputFields: InputFieldInterface[] = [
|
||||||
{
|
{
|
||||||
label: `${parameterDescriptions.d0.name} (DAI)`,
|
label: `${parameterDescriptions.d0.name}`,
|
||||||
description: parameterDescriptions.d0.text,
|
description: parameterDescriptions.d0.text,
|
||||||
value: d0,
|
value: d0,
|
||||||
setter: setD0,
|
setter: setD0,
|
||||||
|
|
@ -35,13 +35,12 @@ export default function CurveDesignInputParams({
|
||||||
suffix: "M",
|
suffix: "M",
|
||||||
format: (n: number) => `$${+(n * 1e-6).toFixed(1)}M`,
|
format: (n: number) => `$${+(n * 1e-6).toFixed(1)}M`,
|
||||||
toText: (n: number) => String(+(n * 1e-6).toFixed(1)),
|
toText: (n: number) => String(+(n * 1e-6).toFixed(1)),
|
||||||
toNum: (n: string) => Math.floor(parseFloat(n) * 1e6),
|
toNum: (n: string) => Math.floor(parseFloat(n) * 1e6)
|
||||||
secondaryColor: true
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<InputParams
|
<InputParamBig
|
||||||
inputFields={inputFields}
|
inputFields={inputFields}
|
||||||
onChangeCommited={setParentCurveParams}
|
onChangeCommited={setParentCurveParams}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ const useStyles = makeStyles(theme => ({
|
||||||
container: {
|
container: {
|
||||||
color: theme.palette.text.secondary,
|
color: theme.palette.text.secondary,
|
||||||
display: "flex",
|
display: "flex",
|
||||||
marginLeft: "6px",
|
|
||||||
fontSize: "0.9rem",
|
fontSize: "0.9rem",
|
||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
transition: "color ease 150ms",
|
transition: "color ease 150ms",
|
||||||
|
|
@ -61,7 +60,7 @@ export default function TextWithPopover({
|
||||||
return (
|
return (
|
||||||
<div className={classes.container}>
|
<div className={classes.container}>
|
||||||
<div aria-describedby={id} onClick={handleClick}>
|
<div aria-describedby={id} onClick={handleClick}>
|
||||||
<Typography gutterBottom>{content}</Typography>
|
<Typography>{content}</Typography>
|
||||||
</div>
|
</div>
|
||||||
<Popover
|
<Popover
|
||||||
PaperProps={{
|
PaperProps={{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,11 @@ export const parameterDescriptions: DescriptionObject = {
|
||||||
text:
|
text:
|
||||||
"The percentage that goes to the funding pool when token holders 'sell' by burning their token at the price determined by the bonding curve"
|
"The percentage that goes to the funding pool when token holders 'sell' by burning their token at the price determined by the bonding curve"
|
||||||
},
|
},
|
||||||
|
vHalflife: {
|
||||||
|
name: "Vesting half life",
|
||||||
|
text:
|
||||||
|
"Tokens that are purchased during the Hatch are locked for 9 weeks and then released slowly such that 50% of the tokens will be able to be sold after this many weeks and 87.5% of the tokens after 3x this many weeks"
|
||||||
|
},
|
||||||
d0: {
|
d0: {
|
||||||
name: "Initial raise",
|
name: "Initial raise",
|
||||||
text: "Amount of funds contributed during the hatch period"
|
text: "Amount of funds contributed during the hatch period"
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ export interface InputFieldInterface {
|
||||||
unit?: string;
|
unit?: string;
|
||||||
prefix?: string;
|
prefix?: string;
|
||||||
suffix?: string;
|
suffix?: string;
|
||||||
secondaryColor?: boolean;
|
|
||||||
toText?(value: number): string;
|
toText?(value: number): string;
|
||||||
toNum?(value: string): number;
|
toNum?(value: string): number;
|
||||||
format(value: number): string;
|
format(value: number): string;
|
||||||
|
|
@ -21,4 +20,5 @@ export interface CurveParamsInterface {
|
||||||
p0: number;
|
p0: number;
|
||||||
p1: number;
|
p1: number;
|
||||||
wFee: number;
|
wFee: number;
|
||||||
|
vHalflife: number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue