From 9bc519be2db8b7d2c252a61a7b7c374dd5990744 Mon Sep 17 00:00:00 2001 From: dapplion Date: Sat, 10 Aug 2019 16:35:12 +0200 Subject: [PATCH 1/3] Implement zargham math review and vesting period floor price --- src/App.tsx | 79 +++++++++++++++++++++++++----- src/PriceSimulationChart.tsx | 36 ++++++++++---- src/SupplyVsDemandChart.tsx | 2 + src/math.ts | 95 ++++++++++++++++++++++++++++++++++-- 4 files changed, 188 insertions(+), 24 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 5964467..c315a0e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -20,10 +20,16 @@ import { getLast, getAvg, pause } from "./utils"; import { getInitialParams, getPriceR, + getMinPrice, + getS, + vest_tokens, + getMinR, getSlippage, getTxDistribution, getDeltaR_priceGrowth, - rv_U + rv_U, + getMedian, + getSum } from "./math"; import { throttle } from "lodash"; // General styles @@ -199,7 +205,7 @@ export default function App() { const { k, // Invariant power kappa (.) R0, // Initial reserve (DAI) - // S0, // initial supply of tokens (token) + S0, // initial supply of tokens (token) V0 // invariant coef } = getInitialParams({ d0, @@ -210,6 +216,7 @@ export default function App() { const [priceTimeseries, setPriceTimeseries] = useState([0]); const [withdrawFeeTimeseries, setWithdrawFeeTimeseries] = useState([0]); + const [floorpriceTimeseries, setFloorpriceTimeseries] = useState([0]); const [totalReserve, setTotalReserve] = useState(R0); const [withdrawCount, setWithdrawCount] = useState(0); const [avgSlippage, setAvgSlippage] = useState(0); @@ -248,48 +255,97 @@ export default function App() { async function simulateRandomDelta() { const R_t: number[] = [R0]; + const S_t: number[] = [S0]; const p_t: number[] = [getPriceR({ R: R0, V0, k })]; const wFee_t: number[] = [0]; const slippage_t: number[] = []; const avgTxSize_t: number[] = []; + // hatchers tokens = S0[section added by Z] + const H_t: number[] = [S0]; // total hatcher tokens not vested + const floorprice_t: number[] = []; // initially the price is the floor as all tokens are hatcher tokens + // Random walk const numSteps = 52; + const u_min = 0.97; + const u_max = 1.04; + const tx_spread = 10; + // vesting(should this be exposed in the app ?) + const cliff = 8; // weeks before vesting starts ~2 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) // numSteps = 52 take 8ms to run setSimulationRunning(true); for (let t = 0; t < numSteps; t++) { - const txsWeek = Math.ceil(t < 5 ? rv_U(0, 5) : rv_U(5, 2 * t)); - const priceGrowth = rv_U(0.99, 1.03); + const txsWeek = rv_U(5, 2 * t + 5); const R = getLast(R_t); - const deltaR = getDeltaR_priceGrowth({ R, k, priceGrowth }); + const S = getLast(S_t); + const H = getLast(H_t); + // enforce the effects of the unvested tokens not being burnable + let u_lower; + if (H === S) { + u_lower = 1; + } else { + const R_ratio = getMinR({ S, H, V0, k }) / R; + u_lower = Math.max(1 - R_ratio, u_min); + } + const priceGrowth = rv_U(u_lower, u_max); + + const deltaR = getDeltaR_priceGrowth({ R, k, priceGrowth }); const R_next = R + deltaR; - const txs = getTxDistribution({ sum: deltaR, num: txsWeek }); + const txs = getTxDistribution({ + sum: deltaR, + num: txsWeek, + spread: tx_spread + }); // Compute slippage - const slippage = getAvg( - txs.map(txR => getSlippage({ R, deltaR: txR, V0, k })) + const slippage_txs = txs.map(txR => + getSlippage({ R, deltaR: txR, V0, k }) ); + const slippage = getMedian(slippage_txs); + const txsWithdraw = txs.filter(tx => tx < 0); - const wFees = -wFee * txsWithdraw.reduce((t, c) => t + c, 0); - const _avgTxSize = - txs.reduce((t, c) => t + Math.abs(c), 0) / txs.length; + const wFees = -wFee * getSum(txsWithdraw); + // txsWithdraw.reduce((t, c) => t + c, 0); + + // Vest + const delta_H = vest_tokens({ week: t, H, halflife, cliff }); + const H_next = H - delta_H; + + // find floor price + const S_next = getS({ R, V0, k }); + const floorprice_next = getMinPrice({ + S: S_next, + H: S0 - H_next, + V0, + k + }); + + const _avgTxSize = getMedian(txsWithdraw); R_t.push(R_next); p_t.push(getPriceR({ R: R_next, V0, k })); slippage_t.push(slippage); avgTxSize_t.push(_avgTxSize); wFee_t.push(getLast(wFee_t) + wFees); + H_t.push(H_next); + floorprice_t.push(floorprice_next); setWithdrawCount(c => c + txsWithdraw.length); // Stop the simulation if it's no longer active if (!simulationActive || !canContinueSimulation) break; } + // floorprice_t is missing one data point + floorprice_t[floorprice_t.length] = floorprice_t[floorprice_t.length - 1]; + setPriceTimeseries(p_t); setWithdrawFeeTimeseries(wFee_t); + setFloorpriceTimeseries(floorprice_t); setAvgSlippage(getAvg(slippage_t)); setAvgTxSize(getAvg(avgTxSize_t)); setTotalReserve(getLast(R_t)); @@ -465,6 +521,7 @@ export default function App() { diff --git a/src/PriceSimulationChart.tsx b/src/PriceSimulationChart.tsx index bcc0e40..df5ab1e 100644 --- a/src/PriceSimulationChart.tsx +++ b/src/PriceSimulationChart.tsx @@ -17,6 +17,7 @@ import { linspace } from "./utils"; const keyHorizontal = "x"; const keyVerticalLeft = "Price (DAI/token)"; const keyVerticalRight = "Total exit tributes (DAI)"; +const keyVerticalLeft2 = "Floor price (DAI/token)"; const useStyles = makeStyles((theme: Theme) => createStyles({ @@ -32,11 +33,13 @@ const useStyles = makeStyles((theme: Theme) => function PriceSimulationChart({ priceTimeseries, withdrawFeeTimeseries, + floorpriceTimeseries, p0, p1 }: { priceTimeseries: number[]; withdrawFeeTimeseries: number[]; + floorpriceTimeseries: number[]; p0: number; p1: number; }) { @@ -51,6 +54,7 @@ function PriceSimulationChart({ data.push({ [keyHorizontal]: t, [keyVerticalLeft]: priceTimeseries[t] || 0, + [keyVerticalLeft2]: floorpriceTimeseries[t] || 0, [keyVerticalRight]: withdrawFeeTimeseries[t] || 0 }); } @@ -70,8 +74,8 @@ function PriceSimulationChart({ const { textAnchor, viewBox, text } = props; return ( @@ -83,10 +87,12 @@ function PriceSimulationChart({ function CustomTooltip({ active, payload, label }: any) { if (active) { const price = payload[0].value; - const exit = payload[1].value; + const floor = payload[1].value; + const exit = payload[2].value; const weekNum = label; const toolTipData: string[][] = [ ["Price", price.toFixed(2), "DAI/tk"], + ["Floor", floor.toFixed(2), "DAI/tk"], ["Exit t.", formatter(exit), "DAI"], ["Week", weekNum, ""] ]; @@ -148,12 +154,10 @@ function PriceSimulationChart({ {/* Capital collected from withdraw fees - AXIS */} @@ -166,7 +170,20 @@ function PriceSimulationChart({ dataKey={keyVerticalLeft} stroke={theme.palette.primary.main} fill={theme.palette.primary.main} + fillOpacity={0.3} + strokeWidth={2} /> + + {/* a - b); + return arr.length % 2 !== 0 ? nums[mid] : (nums[mid - 1] + nums[mid]) / 2; +} + +export function getSum(arr: number[]) { + return arr.reduce((a, b) => a + b, 0); +} From 1c993642af89bff71fd3faf93102cbc0c0a39558 Mon Sep 17 00:00:00 2001 From: dapplion Date: Sat, 10 Aug 2019 17:21:57 +0200 Subject: [PATCH 2/3] Fix math bugs fx --- src/App.tsx | 94 +++++++++++++++++++++++++++++++++++++++++------------ src/math.ts | 20 ++---------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index c315a0e..70501ca 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,7 +23,7 @@ import { getMinPrice, getS, vest_tokens, - getMinR, + getR, getSlippage, getTxDistribution, getDeltaR_priceGrowth, @@ -127,6 +127,9 @@ const useStyles = makeStyles((theme: Theme) => }, descriptionName: { fontWeight: theme.typography.fontWeightBold + }, + descriptionPadding: { + padding: theme.spacing(0.5) } }) ); @@ -158,6 +161,23 @@ const parameterDescriptions = [ } ]; +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", @@ -167,12 +187,12 @@ const resultParameterDescriptions = [ { name: "Funds generated from initial hatch", text: - "Fraction of the funds (theta) raised during the hatch that go directly to the cause" + "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 amount of exit tributes collected from only exit /sell transactions" + "Cumulative sum of exit tributes collected from only exit /sell transactions" }, { name: "Average slippage", @@ -286,10 +306,11 @@ export default function App() { // enforce the effects of the unvested tokens not being burnable let u_lower; - if (H === S) { + if (H > S) { u_lower = 1; } else { - const R_ratio = getMinR({ S, H, V0, k }) / R; + // compute the reserve if all that supply is burned + const R_ratio = getR({ S: S - H, V0, k }) / R; u_lower = Math.max(1 - R_ratio, u_min); } const priceGrowth = rv_U(u_lower, u_max); @@ -328,11 +349,13 @@ export default function App() { const _avgTxSize = getMedian(txsWithdraw); R_t.push(R_next); + S_t.push(S_next); + H_t.push(H_next); p_t.push(getPriceR({ R: R_next, V0, k })); slippage_t.push(slippage); avgTxSize_t.push(_avgTxSize); wFee_t.push(getLast(wFee_t) + wFees); - H_t.push(H_next); + floorprice_t.push(floorprice_next); setWithdrawCount(c => c + txsWithdraw.length); @@ -454,13 +477,16 @@ export default function App() { Preview - 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 parameters and will - never change regardes of the campaign performance, it only - shows how the price will react to reserve changes. - +
+ + 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 + parameters and will never change regardes of the + campaign performance, it only shows how the price will + react to reserve changes. + +
} /> @@ -505,14 +531,40 @@ export default function App() { Simulation - This chart shows a 52 week simulation of discrete - transactions interacting with the token bonding curve. - Each transaction adds or substract reserve to the - system, modifying the price over time. The frequency, - size and direction of each transaction is computed - from a set of bounded random functions. - +
+
+ + This chart shows a 52 week simulation of discrete + transactions interacting with the token bonding + curve. Each transaction adds or substract reserve + to the system, modifying the price over time. The + frequency, size and direction of each transaction + is computed from a set of bounded random + functions. + +
+ + + + {simulationParameterDescriptions.map( + ({ name, text }) => ( + + + + + ) + )} + +
+ + {name} + + + {text} +
+
} /> diff --git a/src/math.ts b/src/math.ts index 02af1a1..4a054bd 100644 --- a/src/math.ts +++ b/src/math.ts @@ -23,7 +23,7 @@ export function getInitialParams({ return { k, R0, S0, V0 }; } -function getR({ S, V0, k }: { S: number; V0: number; k: number }) { +export function getR({ S, V0, k }: { S: number; V0: number; k: number }) { return S ** k / V0; } @@ -31,21 +31,6 @@ export function getS({ R, V0, k }: { R: number; V0: number; k: number }) { return (V0 * R) ** (1 / k); } -// compute the reserve if all that supply is burned -export function getMinR({ - S, - H, - V0, - k -}: { - S: number; - H: number; - V0: number; - k: number; -}) { - return getR({ S: S - H, V0, k }); -} - // compute the price if all that supply is burned export function getMinPrice({ S, @@ -63,7 +48,8 @@ export function getMinPrice({ const myP = getPriceR({ R: myR, V0, k }); // numerical precision make complex numbers just suppress it return Math.abs(myP); } else { - const minR = getMinR({ S, H, V0, k }); + // compute the reserve if all that supply is burned + const minR = getR({ S: S - H, V0, k }); return getPriceR({ R: minR, V0, k }); } } From cce04ea80ec85db286791d326fc147ae8c780612 Mon Sep 17 00:00:00 2001 From: dapplion Date: Sat, 10 Aug 2019 18:04:58 +0200 Subject: [PATCH 3/3] Add popovers with descriptions for each single parameter --- src/App.tsx | 148 +++++++++++---------------------- src/CurveDesignInputParams.tsx | 5 ++ src/InputParams.tsx | 7 +- src/ResultParams.tsx | 8 +- src/SimulationInputParams.tsx | 2 + src/TextWithPopover.tsx | 93 +++++++++++++++++++++ src/parametersDescriptions.ts | 69 +++++++++++++++ src/types.ts | 1 + 8 files changed, 225 insertions(+), 108 deletions(-) create mode 100644 src/TextWithPopover.tsx create mode 100644 src/parametersDescriptions.ts diff --git a/src/App.tsx b/src/App.tsx index 70501ca..dbd38ca 100644 --- a/src/App.tsx +++ b/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() { - {parameterDescriptions.map(({ name, text }) => ( + {[ + parameterDescriptions.theta, + parameterDescriptions.p0, + parameterDescriptions.p1, + parameterDescriptions.wFee, + parameterDescriptions.d0 + ].map(({ name, text }) => ( ))} @@ -478,7 +426,7 @@ export default function App() { - + 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={
- + 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() {
- - {name} - + {name} - {text} + + {text} +
- {simulationParameterDescriptions.map( - ({ name, text }) => ( - - - - - ) - )} + {Object.values( + simulationParameterDescriptions + ).map(({ name, text }) => ( + + + + + ))}
- - {name} - - - {text} -
+ {name} + + + {text} + +
@@ -595,18 +543,18 @@ export default function App() { - {resultParameterDescriptions.map( + {Object.values(resultParameterDescriptions).map( ({ name, text }) => ( ) diff --git a/src/CurveDesignInputParams.tsx b/src/CurveDesignInputParams.tsx index d0d9134..e9f7298 100644 --- a/src/CurveDesignInputParams.tsx +++ b/src/CurveDesignInputParams.tsx @@ -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, diff --git a/src/InputParams.tsx b/src/InputParams.tsx index fd9f603..3d06aaa 100644 --- a/src/InputParams.tsx +++ b/src/InputParams.tsx @@ -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 ( - - {label} - + diff --git a/src/ResultParams.tsx b/src/ResultParams.tsx index 26ff4b6..9642b95 100644 --- a/src/ResultParams.tsx +++ b/src/ResultParams.tsx @@ -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 (
- {resultFields.map(({ label, value }) => ( + {resultFields.map(({ label, description, value }) => ( - - {label} - + diff --git a/src/SimulationInputParams.tsx b/src/SimulationInputParams.tsx index e02f36e..93dcc55 100644 --- a/src/SimulationInputParams.tsx +++ b/src/SimulationInputParams.tsx @@ -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, diff --git a/src/TextWithPopover.tsx b/src/TextWithPopover.tsx new file mode 100644 index 0000000..781e1e5 --- /dev/null +++ b/src/TextWithPopover.tsx @@ -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 ( +
+
+ {content} +
+ + + {content} + + {popoverText} + + + +
+ ); +} diff --git a/src/parametersDescriptions.ts b/src/parametersDescriptions.ts new file mode 100644 index 0000000..0b7ebf7 --- /dev/null +++ b/src/parametersDescriptions.ts @@ -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" + } +}; diff --git a/src/types.ts b/src/types.ts index 2fcc5e2..e0f426c 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ export interface InputFieldInterface { label: string; + description: string; value: number; setter(newValue: any): void; min: number;
- - {name} - + {name} - {text} + + {text} +