From 36767f33c6d96ac679fe9f576cfc55297992f24c Mon Sep 17 00:00:00 2001 From: firerum Date: Thu, 19 Sep 2024 23:25:41 +0100 Subject: [PATCH 1/3] switched to table format with sorting between ascending and descending order to track energy generated for each token, and also for better data visualization --- .../leaderboards/tokens-difficulty-chart.tsx | 185 ++++++++++-------- pages/governance/index.tsx | 12 +- 2 files changed, 109 insertions(+), 88 deletions(-) diff --git a/components/leaderboards/tokens-difficulty-chart.tsx b/components/leaderboards/tokens-difficulty-chart.tsx index 12d9035f..f68c9b1f 100644 --- a/components/leaderboards/tokens-difficulty-chart.tsx +++ b/components/leaderboards/tokens-difficulty-chart.tsx @@ -1,91 +1,110 @@ -import { TrendingUp } from "lucide-react" -import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from "recharts" +import React, { useState } from 'react'; import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@components/ui/card" + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@components/ui/card'; +import numeral from 'numeral'; +import { ChartConfig } from '@components/ui/chart'; import { - ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@components/ui/chart" + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@components/ui/table"; -export function TokensDifficultyChart({ chartData, chartConfig }: { chartData: any[], chartConfig: ChartConfig }) { - return ( - - - Energy Output of Staked Tokens - Normalized with Difficulty Adjustment - - - - +export function TokensDifficultyChart({ chartData, chartConfig }: { chartData: any[], chartConfig: ChartConfig }) { + // State for sorting between ascending and descending + const [sortConfig, setSortConfig] = useState<{ + key: keyof ChartDataItem; + direction: 'ascending' | 'descending'; + }>({ key: 'score', direction: 'descending' }); - - { + const sortableItems = [...chartData]; + sortableItems.sort((a, b) => { + if (a[sortConfig.key] < b[sortConfig.key]) { + return sortConfig.direction === 'ascending' ? -1 : 1; + } + if (a[sortConfig.key] > b[sortConfig.key]) { + return sortConfig.direction === 'ascending' ? 1 : -1; + } + return 0; + }); + return sortableItems; + }, [chartData, sortConfig]); - /> - - - } + const requestSort = (key: keyof ChartDataItem) => { + let direction: 'ascending' | 'descending' = 'ascending'; + if ( + sortConfig.key === key && + sortConfig.direction === 'ascending' + ) { + direction = 'descending'; + } + setSortConfig({ key, direction }); + }; - /> - - - `${value.toFixed(0)}`} - /> - - - - - {/* -
- Trending up by 5.2% this month -
-
- Showing total tokens for the last 6 months -
-
*/} -
- ) + return ( + + + Energy Output of Staked Tokens + + Normalized with Difficulty Adjustment + + + +
+ + + + requestSort('id')} + className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider cursor-pointer" + > + Token{' '} + {sortConfig.key === 'id' && + (sortConfig.direction === 'ascending' + ? '▲' + : '▼')} + + requestSort('score')} + className="px-6 py-3 text-left text-xs font-medium uppercase tracking-wider cursor-pointer" + > + Energy Output{' '} + {sortConfig.key === 'score' && + (sortConfig.direction === 'ascending' + ? '▲' + : '▼')} + + + + + {sortedData.map((item) => ( + + + {item.id} + + + {numeral(item.score).format('0,0')} + + + ))} + +
+
+
+
+ ); } diff --git a/pages/governance/index.tsx b/pages/governance/index.tsx index e53e6011..6db15681 100644 --- a/pages/governance/index.tsx +++ b/pages/governance/index.tsx @@ -44,7 +44,7 @@ const Card: React.FC = ({ href, src, alt, title, subtitle }) => ( 'overflow-hidden' )} > -
+
{alt} = ({ href, src, alt, title, subtitle }) => ( )} />
-
+

{title}

{subtitle}

@@ -207,7 +207,7 @@ export default function Governance({ data }: Props) {
-
+
Proposals @@ -217,7 +217,7 @@ export default function Governance({ data }: Props) { - @@ -226,7 +226,7 @@ export default function Governance({ data }: Props) { -
+
{cards.map((card, index) => ( ))} @@ -242,6 +242,8 @@ export default function Governance({ data }: Props) { export const getServerSideProps: GetServerSideProps = async () => { try { + // TODO: utilize the new proposal data provided by chainhooks to get initial list of proposals + // we will still need to enrich this data with proposal metadata, tbd const [proposals, transactions] = await Promise.all([ getProposals(), fetchAllContractTransactions( From 0f87ff20d2ae7251f9bc5ed0a071c674ea8b5174 Mon Sep 17 00:00:00 2001 From: firerum Date: Fri, 20 Sep 2024 00:38:55 +0100 Subject: [PATCH 2/3] UI and functionality change --- components/leaderboards/lands-chart.tsx | 209 ++++++++++++++---------- next-env.d.ts | 2 +- pages/leaderboard.tsx | 70 +++++--- 3 files changed, 179 insertions(+), 102 deletions(-) diff --git a/components/leaderboards/lands-chart.tsx b/components/leaderboards/lands-chart.tsx index a0d0a5b0..92997784 100644 --- a/components/leaderboards/lands-chart.tsx +++ b/components/leaderboards/lands-chart.tsx @@ -1,91 +1,136 @@ -import { TrendingUp } from "lucide-react" -import { Bar, BarChart, CartesianGrid, LabelList, XAxis, YAxis } from "recharts" +import { TrendingUp } from "lucide-react"; import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle, -} from "@components/ui/card" + Bar, + BarChart, + CartesianGrid, + XAxis, + YAxis, + ResponsiveContainer, + Tooltip, + Cell, +} from "recharts"; import { - ChartConfig, - ChartContainer, - ChartTooltip, - ChartTooltipContent, -} from "@components/ui/chart" + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@components/ui/card"; +import { + ChartConfig, + ChartContainer, + ChartTooltip, + ChartTooltipContent, +} from "@components/ui/chart"; +import { useState, useEffect } from "react"; export function LandsChart({ chartData, chartConfig }: { chartData: any[], chartConfig: ChartConfig }) { - return ( - - - Total Tokens Staked - By Percentage of Total Supply - - - - (false); + + useEffect(() => { + function handleResize() { + setIsMobile(window.innerWidth < 768); + } + handleResize(); + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); - > + // generates unique colors for each token + const COLORS = chartData.map((_, index) => + `hsl(${(index * 137.508) % 360}, 65%, 55%)` + ); - - item.id.length * (isMobile ? 7 : 10))), + isMobile ? 100 : 150 + ); - /> - - - } + // set maximum height for the chart container + const maxChartHeight = 400; - /> - - - `${(value * 100).toFixed(2)}%`} - /> - - - - - {/* -
- Trending up by 5.2% this month -
-
- Showing total tokens for the last 6 months -
-
*/} -
- ) + return ( + + + Total Tokens Staked + By Percentage of Total Supply + + +
+ maxChartHeight + ? chartData.length * (isMobile ? 40 : 30) + : maxChartHeight + } + > + + {/* I got rid of vertical grid lines */} + + + + `${(value * 100).toFixed(2)}%`} + contentStyle={{ + backgroundColor: "#170202", // tooltip background color + borderColor: "#710707", + borderRadius: "5px", + padding: "5px 19px", + }} + itemStyle={{ color: "#fff" }} // tooltip text color + /> + + {chartData.map((entry, index) => ( + + ))} + + + +
+
+ {/* +
+ Trending up by 5.2% this month +
+
+ Showing total tokens for the last 6 months +
+
*/} +
+ ); } diff --git a/next-env.d.ts b/next-env.d.ts index 4f11a03d..a4a7b3f5 100644 --- a/next-env.d.ts +++ b/next-env.d.ts @@ -2,4 +2,4 @@ /// // 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. diff --git a/pages/leaderboard.tsx b/pages/leaderboard.tsx index ac7adbab..e227a605 100644 --- a/pages/leaderboard.tsx +++ b/pages/leaderboard.tsx @@ -56,26 +56,58 @@ export const getStaticProps: GetStaticProps = async () => { }; for (let i = 1; i <= Number(uniqueLandTypes); i++) { - const amount = await clarigen.roOk(landsContract.getTotalSupply(i)) - const assetContract: string = await clarigen.ro(landsContract.getLandAssetContract(i)) - if (Number(amount)) { - const tokenMetadata = await getLand(assetContract) - - const tokens = await velarApi.tokens(tokenMetadata.wraps.symbol) - - const price = Number(tokens[0]?.price) || 0.000000000001 - - chartData0.push({ id: tokenMetadata.name, score: Number(amount) / Math.pow(10, tokenMetadata.wraps.decimals || 6) * Number(price), fill: `hsl(var(--background))` }); - chartConfig0[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } - - chartData1.push({ id: tokenMetadata.name, score: Number(amount) / tokenMetadata.wraps.totalSupply, fill: `hsl(var(--background))` }); - chartConfig1[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } - - const landDifficulty: bigint = await clarigen.ro(landsContract.getLandDifficulty(i)) - chartData2.push({ id: tokenMetadata.name, score: Number(amount) / Number(landDifficulty), fill: `hsl(var(--background))` }); - chartConfig2[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } + const amount = await clarigen.roOk(landsContract.getTotalSupply(i)); + const assetContract: string = await clarigen.ro(landsContract.getLandAssetContract(i)); + + const tokenMetadata = await getLand(assetContract); + + // Add null checks + if (Number(amount) && tokenMetadata && tokenMetadata.wraps && tokenMetadata.wraps.symbol) { + const tokens = await velarApi.tokens(tokenMetadata.wraps.symbol); + const price = Number(tokens[0]?.price) || 0.000000000001; + + chartData0.push({ + id: tokenMetadata.name, + score: + (Number(amount) / Math.pow(10, tokenMetadata.wraps.decimals || 6)) * + Number(price), + fill: `hsl(var(--background))`, + }); + chartConfig0[tokenMetadata.name] = { + label: tokenMetadata.name, + color: `hsl(var(--secondary))`, + }; + + chartData1.push({ + id: tokenMetadata.name, + score: Number(amount) / tokenMetadata.wraps.totalSupply, + fill: `hsl(var(--background))`, + }); + chartConfig1[tokenMetadata.name] = { + label: tokenMetadata.name, + color: `hsl(var(--secondary))`, + }; + + const landDifficulty: bigint = await clarigen.ro( + landsContract.getLandDifficulty(i) + ); + chartData2.push({ + id: tokenMetadata.name, + score: Number(amount) / Number(landDifficulty), + fill: `hsl(var(--background))`, + }); + chartConfig2[tokenMetadata.name] = { + label: tokenMetadata.name, + color: `hsl(var(--secondary))`, + }; + } else { + console.warn( + `Skipping asset contract due to missing data: ${assetContract}` + ); + // Optionally handle the error or provide default values } - } + } + From 0fa5de0a5f95e170ffd1f4e951160ce3f1e37e4e Mon Sep 17 00:00:00 2001 From: firerum Date: Fri, 20 Sep 2024 00:45:08 +0100 Subject: [PATCH 3/3] UI and functionality change --- pages/leaderboard.tsx | 70 ++++++++++++------------------------------- 1 file changed, 19 insertions(+), 51 deletions(-) diff --git a/pages/leaderboard.tsx b/pages/leaderboard.tsx index e227a605..ac7adbab 100644 --- a/pages/leaderboard.tsx +++ b/pages/leaderboard.tsx @@ -56,58 +56,26 @@ export const getStaticProps: GetStaticProps = async () => { }; for (let i = 1; i <= Number(uniqueLandTypes); i++) { - const amount = await clarigen.roOk(landsContract.getTotalSupply(i)); - const assetContract: string = await clarigen.ro(landsContract.getLandAssetContract(i)); - - const tokenMetadata = await getLand(assetContract); - - // Add null checks - if (Number(amount) && tokenMetadata && tokenMetadata.wraps && tokenMetadata.wraps.symbol) { - const tokens = await velarApi.tokens(tokenMetadata.wraps.symbol); - const price = Number(tokens[0]?.price) || 0.000000000001; - - chartData0.push({ - id: tokenMetadata.name, - score: - (Number(amount) / Math.pow(10, tokenMetadata.wraps.decimals || 6)) * - Number(price), - fill: `hsl(var(--background))`, - }); - chartConfig0[tokenMetadata.name] = { - label: tokenMetadata.name, - color: `hsl(var(--secondary))`, - }; - - chartData1.push({ - id: tokenMetadata.name, - score: Number(amount) / tokenMetadata.wraps.totalSupply, - fill: `hsl(var(--background))`, - }); - chartConfig1[tokenMetadata.name] = { - label: tokenMetadata.name, - color: `hsl(var(--secondary))`, - }; - - const landDifficulty: bigint = await clarigen.ro( - landsContract.getLandDifficulty(i) - ); - chartData2.push({ - id: tokenMetadata.name, - score: Number(amount) / Number(landDifficulty), - fill: `hsl(var(--background))`, - }); - chartConfig2[tokenMetadata.name] = { - label: tokenMetadata.name, - color: `hsl(var(--secondary))`, - }; - } else { - console.warn( - `Skipping asset contract due to missing data: ${assetContract}` - ); - // Optionally handle the error or provide default values + const amount = await clarigen.roOk(landsContract.getTotalSupply(i)) + const assetContract: string = await clarigen.ro(landsContract.getLandAssetContract(i)) + if (Number(amount)) { + const tokenMetadata = await getLand(assetContract) + + const tokens = await velarApi.tokens(tokenMetadata.wraps.symbol) + + const price = Number(tokens[0]?.price) || 0.000000000001 + + chartData0.push({ id: tokenMetadata.name, score: Number(amount) / Math.pow(10, tokenMetadata.wraps.decimals || 6) * Number(price), fill: `hsl(var(--background))` }); + chartConfig0[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } + + chartData1.push({ id: tokenMetadata.name, score: Number(amount) / tokenMetadata.wraps.totalSupply, fill: `hsl(var(--background))` }); + chartConfig1[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } + + const landDifficulty: bigint = await clarigen.ro(landsContract.getLandDifficulty(i)) + chartData2.push({ id: tokenMetadata.name, score: Number(amount) / Number(landDifficulty), fill: `hsl(var(--background))` }); + chartConfig2[tokenMetadata.name] = { label: tokenMetadata.name, color: `hsl(var(--secondary))` } } - } - + }