Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performance chart public launch #321

Merged
merged 7 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/front-end/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"plugins": ["react", "@typescript-eslint"],
"rules": {
"react/prop-types": "off",
"react/react-in-jsx-scope": "off",
"no-debugger": "off",
"@typescript-eslint/no-empty-function": "off",
"@typescript-eslint/ban-ts-comment": "off",
Expand Down
14,003 changes: 303 additions & 13,700 deletions packages/front-end/package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions packages/front-end/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@
"@web3-onboard/walletconnect": "^2.0.1",
"axios": "^0.26.1",
"buffer": "^6.0.3",
"dayjs": "^1.11.7",
bestatigen marked this conversation as resolved.
Show resolved Hide resolved
"dotenv": "^16.0.0",
"env-cmd": "^10.1.0",
"ethers": "^5.6.4",
"fathom-client": "^3.5.0",
"framer-motion": "^6.5.1",
"graphql": "^16.5.0",
"greeks": "^1.0.0",
"humanize-duration": "^3.27.3",
Expand Down
144 changes: 0 additions & 144 deletions packages/front-end/src/components/VaultChart.tsx

This file was deleted.

17 changes: 0 additions & 17 deletions packages/front-end/src/components/VaultPerformance.tsx

This file was deleted.

5 changes: 5 additions & 0 deletions packages/front-end/src/components/VaultPerformance/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Vault performance chart component

The vault performance chart is made up of a series of subcomponents with a single graph query at the top. This query accesses the `pricePerShares` graph data, skipping the first two entries. This is because the first two epochs were used for testing and pre-public launch.

An effect in the main `VaultPerformance` component handles adjusting each of the epoch nodes by deducting the growth percentage at the third epoch from each subsequent epoch. This allows us to display chart data from the public launch, corrected as if the third epoch were zero percent.
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import type { QueryData, ChartData } from "./VaultPerformance.types";

import { gql, useQuery } from "@apollo/client";
import { captureException } from "@sentry/react";
import { useState, useEffect } from "react";
import { AnimatePresence } from "framer-motion";

import { toTwoDecimalPlaces } from "src/utils/rounding";

import { Chart } from "./subcomponents/Chart";
import { Disclaimer } from "./subcomponents/Disclaimer";
import { Error } from "./subcomponents/Error";
import { Loading } from "./subcomponents/Loading";
import { FadeWrapper } from "./subcomponents/FadeWrapper";
import { Stats } from "./subcomponents/Stats";

export const VaultPerformance = () => {
const [chartData, setChartData] = useState<ChartData[]>([]);

const { loading, error, data } = useQuery<QueryData>(
gql`
query {
pricePerShares(
orderBy: "epoch"
orderDirection: "asc"
first: 1000
skip: 2
) {
epoch
growthSinceFirstEpoch
timestamp
}
}
`,
{
onError: (err) => {
captureException(err);
console.error(err);
},
}
);

useEffect(() => {
if (data) {
const { pricePerShares } = data;

const publicLaunchOffset = parseFloat(
pricePerShares[0].growthSinceFirstEpoch
);

const adjustedChartData = pricePerShares.map((pricePoint) => {
const pricePointGrowth = parseFloat(pricePoint.growthSinceFirstEpoch);
const growthSinceFirstEpoch = toTwoDecimalPlaces(
pricePointGrowth - publicLaunchOffset
);

return {
...pricePoint,
growthSinceFirstEpoch,
};
});

setChartData(adjustedChartData);
}
}, [data]);

return (
<AnimatePresence exitBeforeEnter>
{loading && (
<FadeWrapper key="loading">
<Loading />
</FadeWrapper>
)}

{error && (
<FadeWrapper key="error">
<Error />
</FadeWrapper>
)}

{data && (
<FadeWrapper key="data">
<Stats
cumulativeYield={
chartData[chartData.length - 1]?.growthSinceFirstEpoch
}
/>
<Chart chartData={chartData} />
<Disclaimer />
</FadeWrapper>
)}
</AnimatePresence>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface PricePerShareEpoch {
epoch: string;
growthSinceFirstEpoch: string;
timestamp: string;
__typename: string;
}

export interface QueryData {
pricePerShares: PricePerShareEpoch[];
}

export interface ChartData
extends Omit<PricePerShareEpoch, "growthSinceFirstEpoch"> {
growthSinceFirstEpoch: number;
}

export interface CustomTooltipProps {
active?: boolean;
payload?: [
{
value: string;
payload: { epoch: string };
}
];
label?: string;
}

export interface ChartProps {
chartData: ChartData[];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import type { ChartProps, CustomTooltipProps } from "../VaultPerformance.types";

import dayjs from "dayjs";
import {
LineChart,
Line,
CartesianGrid,
XAxis,
YAxis,
Tooltip,
ResponsiveContainer,
Legend,
} from "recharts";

const CustomTooltip = ({ active, payload, label }: CustomTooltipProps) => {
if (label && active && payload && payload.length) {
return (
<div
className="custom-tooltip bg-bone bg-opacity-90 border-black p-4 border-2 rounded-xl"
role="dialog"
>
<p>{dayjs.unix(parseInt(label)).format("DD MMM YY")}</p>
<p className="label">{`Yield: ${payload[0].value}%`}</p>
<p className="label">{`Epoch: ${payload[0].payload.epoch}`}</p>
</div>
);
}

return null;
};

export const Chart = ({ chartData }: ChartProps) => (
<div
className="p-8 flex flex-col lg:flex-row h-full justify-around"
role="graphics-document"
>
<ResponsiveContainer width={"100%"} height={400} className="">
<LineChart
data={chartData}
margin={{ top: 5, right: 40, bottom: 5, left: 20 }}
>
<Line
type="natural"
dataKey="growthSinceFirstEpoch"
// TODO access color through Tailwind helpers
stroke="black"
strokeWidth={2}
/>
<CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
<XAxis
type="number"
scale="time"
domain={["dataMin", "dataMax"]}
dataKey="timestamp"
angle={0}
minTickGap={16}
tickFormatter={(value: string) =>
dayjs.unix(parseInt(value)).format("DD MMM")
}
/>
<YAxis tickFormatter={(value: string) => `${value}%`} />
<Tooltip content={<CustomTooltip />} />
<Legend verticalAlign="bottom" formatter={() => "Cumulative Yield"} />
</LineChart>
</ResponsiveContainer>
</div>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { DHV_NAME } from "src/config/constants";
import { DISCORD_LINK } from "src/config/links";

export const Disclaimer = () => (
<small className="pb-8 px-8 block mx-[20%]">
{`This chart shows the ${DHV_NAME} share price change since the third epoch (Alpha public launch). Data before this is the result of testing and is excluded. If you have any questions, feel free to `}
<a href={DISCORD_LINK} target="_blank" rel="noopener noreferrer">
{`reach out to us via our Discord.`}
</a>
</small>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const Error = () => (
<p className="p-8 pt-12 text-center">{`Sorry but we're having difficult fetching that data right now. Please try again later.`}</p>
);
Loading