Skip to content
Open
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
237 changes: 153 additions & 84 deletions components/leaderboards/lands-tvl-chart.tsx
Original file line number Diff line number Diff line change
@@ -1,92 +1,161 @@
import { TrendingUp } from "lucide-react"
import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from "recharts"
import React, { useState, useEffect } from 'react';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@components/ui/card"
PieChart,
Pie,
Cell,
Tooltip,
ResponsiveContainer,
} from 'recharts';
import {
ChartConfig,
ChartContainer,
ChartTooltip,
ChartTooltipContent,
} from "@components/ui/chart"
import numeral from "numeral"
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@components/ui/card';
import numeral from 'numeral';

export function LandsTVLChart({ chartData, chartConfig }: { chartData: any[], chartConfig: ChartConfig }) {
return (
<Card>
<CardHeader>
<CardTitle>Stake-to-Earn TVL</CardTitle>
<CardDescription>Value in USD of all tokens staked on Charisma</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={chartConfig}>
<BarChart
style={{ fill: 'white' }}
accessibilityLayer
data={chartData}
layout="vertical"
margin={{
right: 16,
}}
// I switched to dynamic colors incase the number of tokens increases
const generateColors = (numColors: number): string[] => {
const colors: string[] = [];
const saturation = 70;
const lightness = 50;
for (let i = 0; i < numColors; i++) {
const hue = Math.round((360 / numColors) * i);
colors.push(`hsl(${hue}, ${saturation}%, ${lightness}%)`);
}
return colors;
};

>
interface ChartData {
id: string;
score: number;
}

interface Props {
chartData: ChartData[];
}

// Custom hook to get the window width
// the legend was overlapping the piechart on mobile devices so i decided to use the function below
function useWindowWidth() {
const [width, setWidth] = useState<number | undefined>(undefined);

useEffect(() => {
if (typeof window !== 'undefined') {
const handleResize = () => {
setWidth(window.innerWidth);
};
window.addEventListener('resize', handleResize);
// Set initial width
handleResize();
return () => window.removeEventListener('resize', handleResize);
}
}, []);

return width;
}

export function LandsTVLChart({ chartData }: Props) {
const width = useWindowWidth();
const isMobile = width !== undefined && width < 600;

<CartesianGrid horizontal={false} />
<YAxis
dataKey="id"
type="category"
tickLine={false}
tickMargin={10}
axisLine={false}
hide
// calculate total TVL and percentage share for each token
const totalTVL = chartData.reduce((sum, entry) => sum + entry.score, 0);
const dataWithPercentages = chartData.map((entry) => ({
...entry,
percentage: ((entry.score / totalTVL) * 100).toFixed(2),
}));

/>
<XAxis dataKey="score" type="number" hide />
<ChartTooltip
cursor={false}
content={
<ChartTooltipContent indicator="line" />
}
const COLORS = generateColors(chartData.length);

/>
<Bar
dataKey="score"
layout="vertical"
fill="var(--color-tokens)"
radius={4}
>
<LabelList
dataKey="id"
position="insideLeft"
offset={8}
className="fill-[--color-label]"
fontSize={12}
/>
<LabelList
dataKey="score"
position="right"
offset={8}
className="fill-foreground"
fontSize={12}
formatter={(value: number) => numeral(value).format('$0,0.00')}
/>
</Bar>
</BarChart>
</ChartContainer>
</CardContent>
{/* <CardFooter className="flex-col items-start gap-2 text-sm">
<div className="flex gap-2 font-medium leading-none">
Trending up by 5.2% this month <TrendingUp className="h-4 w-4" />
</div>
<div className="leading-none text-muted-foreground">
Showing total tokens for the last 6 months
</div>
</CardFooter> */}
</Card>
)
return (
<Card>
<CardHeader>
<CardTitle>Stake-to-Earn TVL</CardTitle>
<CardDescription>
Distribution of Total Value Locked (TVL) across staked tokens on Charisma
</CardDescription>
</CardHeader>
<CardContent>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
width: '100%',
outline: '0',
}}
>
<ResponsiveContainer width="100%" height={isMobile ? 250 : 500}>
<PieChart>
<Pie
data={dataWithPercentages}
cx="50%"
cy={isMobile ? '45%' : '50%'} // Move chart up on mobile
innerRadius={isMobile ? 60 : 100}
outerRadius={isMobile ? 100 : 160}
fill="#8884d8"
paddingAngle={3}
dataKey="score"
nameKey="id"
>
{dataWithPercentages.map((entry, index) => (
<Cell
key={`cell-${index}`}
fill={COLORS[index % COLORS.length]}
/>
))}
</Pie>
<Tooltip
formatter={(value: number, name: string, props: any) => [
numeral(value).format('$0,0.00'),
`${props.payload.id}`,
]}
contentStyle={{
backgroundColor: '#170202',
borderColor: '#ccc',
borderRadius: '5px',
padding: '5px',
}}
itemStyle={{ color: '#fff' }}
/>
</PieChart>
</ResponsiveContainer>
{/* Custom Legend */}
<div
style={{
fontSize: '12px',
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'center',
marginTop: '10px',
maxWidth: '100%',
}}
>
{dataWithPercentages.map((item, index) => (
<div
key={`legend-item-${index}`}
style={{
display: 'flex',
alignItems: 'center',
margin: '5px 10px',
}}
>
<div
style={{
width: '10px',
height: '10px',
backgroundColor: COLORS[index % COLORS.length],
marginRight: '5px',
}}
></div>
<span>{`${item.id}: ${item.percentage}%`}</span>
</div>
))}
</div>
</div>
</CardContent>
</Card>
);
}
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
5 changes: 3 additions & 2 deletions pages/api/v0/crons/stimulate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ export default async function stimulateSwapAPI(
contractAddress: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-path2',
functionName: 'do-swap',
args: [
uintCV(6000000),
uintCV(20000000),
principalCV('SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.wstx'),
principalCV('SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.liquid-staked-charisma'),
// principalCV('SP2ZNGJ85ENDY6QRHQ5P2D4FXKGZWCKTB2T0Z55KS.liquid-staked-charisma'),
principalCV('SP3NE50GEXFG9SZGTT51P40X2CKYSZ5CC4ZTZ7A2G.welshcorgicoin-token'),
principalCV('SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-share-fee-to'),
],
fee: 10000
Expand Down
2 changes: 1 addition & 1 deletion pages/leaderboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export default function LeaderboardPage({ wchaPriceData, holders, expTotalSupply
<RewardsLeaderboardTable wchaPriceData={wchaPriceData} holders={holders} topRewardedPlayers={topRewardedPlayers} />
</TabsContent>
<TabsContent value="3">
<LandsTVLChart chartData={chartData0} chartConfig={chartConfig0} />
<LandsTVLChart chartData={chartData0} />
</TabsContent>
<TabsContent value="4">
<TokensDifficultyChart chartData={chartData2} chartConfig={chartConfig2} />
Expand Down
29 changes: 27 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9419,6 +9419,15 @@ string-width@^3.0.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"

string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
version "4.2.3"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
dependencies:
emoji-regex "^8.0.0"
is-fullwidth-code-point "^3.0.0"
strip-ansi "^6.0.1"

string-width@^5.0.1, string-width@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
Expand Down Expand Up @@ -9482,7 +9491,7 @@ stringify-entities@^4.0.0:
character-entities-html4 "^2.0.0"
character-entities-legacy "^3.0.0"

"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
Expand All @@ -9496,6 +9505,13 @@ strip-ansi@^5.1.0:
dependencies:
ansi-regex "^4.1.0"

strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
dependencies:
ansi-regex "^5.0.1"

strip-ansi@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
Expand Down Expand Up @@ -10681,7 +10697,16 @@ word-wrapper@^1.0.7:
resolved "https://registry.yarnpkg.com/word-wrapper/-/word-wrapper-1.0.7.tgz#1f14afebf66dfdf0fef55efd37184efbd08c28b6"
integrity sha512-VOPBFCm9b6FyYKQYfn9AVn2dQvdR/YOVFV6IBRA1TBMJWKffvhEX1af6FMGrttILs2Q9ikCRhLqkbY2weW6dOQ==

"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
dependencies:
ansi-styles "^4.0.0"
string-width "^4.1.0"
strip-ansi "^6.0.0"

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
Expand Down