From 9a9a3529b0b6fb09447011d7cd9fe68cad3e4c7c Mon Sep 17 00:00:00 2001 From: SecretSaturn <94856309+SecretSaturn@users.noreply.github.com> Date: Sun, 3 Nov 2024 21:02:27 +0100 Subject: [PATCH 1/5] bump mixpanel --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 09e67c9b..570b8002 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,7 @@ }, "devDependencies": { "@keplr-wallet/types": "^0.12.43", - "@types/mixpanel-browser": "^2.38.1", + "@types/mixpanel-browser": "^2.50.2", "@types/react": "^18.0.26", "@types/react-dom": "^18.3.1", "husky": "^8.0.3", @@ -9441,9 +9441,9 @@ } }, "node_modules/@types/mixpanel-browser": { - "version": "2.47.4", - "resolved": "https://registry.npmjs.org/@types/mixpanel-browser/-/mixpanel-browser-2.47.4.tgz", - "integrity": "sha512-wAwhSaIk//XY+O5Y8vnlb0Dc9Rpt0s+yHRXf1cGIYM4G5efzRjNeqWEqROf4qzP9FUgVE2M0Z8Pg9BV8Dt46yw==", + "version": "2.50.2", + "resolved": "https://registry.npmjs.org/@types/mixpanel-browser/-/mixpanel-browser-2.50.2.tgz", + "integrity": "sha512-Iw8cBzplUPfHoeYuasqeYwdbGTNXhN+5kFT9kU+C7zm0NtaiPpKoiuzITr2ZH9KgBsWi2MbG0FOzIg9sQepauQ==", "dev": true }, "node_modules/@types/ms": { diff --git a/package.json b/package.json index 8035f5d7..63f9723a 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ }, "devDependencies": { "@keplr-wallet/types": "^0.12.43", - "@types/mixpanel-browser": "^2.38.1", + "@types/mixpanel-browser": "^2.50.2", "@types/react": "^18.0.26", "@types/react-dom": "^18.3.1", "husky": "^8.0.3", From 277dd6abb365cf2f16c4cf6c22d22ccac3cbd911 Mon Sep 17 00:00:00 2001 From: alexander-sei <94856309+SecretSaturn@users.noreply.github.com> Date: Mon, 11 Nov 2024 02:53:47 +0100 Subject: [PATCH 2/5] Performance improvements for relayer analytics --- src/context/APIContext.tsx | 13 ++++++++++-- .../components/RelayerChartTotal.tsx | 21 ++++--------------- .../RelayerChartWithChainSlider.tsx | 20 +++++++----------- .../components/RelayerChartWithDateSlider.tsx | 16 +++++++------- .../RelayerChartWithProviderSlider.tsx | 20 ++++++++---------- src/utils/commons.ts | 1 + 6 files changed, 40 insertions(+), 51 deletions(-) diff --git a/src/context/APIContext.tsx b/src/context/APIContext.tsx index 2d256a27..1550e024 100644 --- a/src/context/APIContext.tsx +++ b/src/context/APIContext.tsx @@ -4,7 +4,7 @@ import { SecretNetworkClient } from 'secretjs' import { useUserPreferencesStore } from 'store/UserPreferences' import { Currency } from 'types/Currency' import { Nullable } from 'types/Nullable' -import { allTokens, coinGeckoCurrencyMap, sortDAppsArray } from 'utils/commons' +import { allTokens, bech32PrefixToChainName, coinGeckoCurrencyMap, sortDAppsArray } from 'utils/commons' import { SECRET_LCD, SECRET_CHAIN_ID } from 'utils/config' const APIContext = createContext(null) @@ -231,7 +231,16 @@ const APIContextProvider = ({ children }: any) => { .then((response) => (response as any).json()) .catch((error: any) => console.error(error)) .then((response) => { - setAnalyticsData4(response) + const filteredData = response + .filter((entry: any) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret') + .map((entry: any) => { + const chainName = bech32PrefixToChainName.get(entry.IBC_Counterpart) || entry.IBC_Counterpart + return { + ...entry, + IBC_Counterpart: chainName + } + }) + setAnalyticsData4(filteredData) }) const LAVENDERFIVE_API_URL_SECRET_STATUS = `https://api.lavenderfive.com/networks/secretnetwork` diff --git a/src/pages/analytics/components/RelayerChartTotal.tsx b/src/pages/analytics/components/RelayerChartTotal.tsx index 5d0e74fc..dee4af81 100644 --- a/src/pages/analytics/components/RelayerChartTotal.tsx +++ b/src/pages/analytics/components/RelayerChartTotal.tsx @@ -1,5 +1,5 @@ import { useContext, useMemo } from 'react' -import { bech32PrefixToChainName, formatNumber } from 'utils/commons' +import { formatNumber } from 'utils/commons' import Tooltip from '@mui/material/Tooltip' import { Chart as ChartJS, @@ -18,13 +18,6 @@ import { APIContext } from 'context/APIContext' ChartJS.register(CategoryScale, LinearScale, BarElement, ChartTooltip, Legend, BarController) -type Entry = { - Date: string - IBC_Counterpart: string - Relayer: string - Transactions: number -} - export default function RelayerChartTotal() { const { theme } = useUserPreferencesStore() const { analyticsData4 } = useContext(APIContext) @@ -35,12 +28,8 @@ export default function RelayerChartTotal() { const datesSet = new Set() const dataMatrix: Record = {} - const filteredData = analyticsData4.filter( - (entry: Entry) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret' - ) - // Collect and sort dates - for (const entry of filteredData) { + for (const entry of analyticsData4) { const date = new Date(entry.Date).toISOString().split('T')[0] datesSet.add(date) } @@ -56,13 +45,11 @@ export default function RelayerChartTotal() { ) // Process entries and populate dataMatrix - for (const entry of filteredData) { + for (const entry of analyticsData4) { const date = new Date(entry.Date).toISOString().split('T')[0] const dateIndex = dateIndexMap[date] - const label = `${bech32PrefixToChainName.get(entry.IBC_Counterpart) || entry.IBC_Counterpart} - ${ - entry.Relayer || 'Other' - }` + const label = `${entry.IBC_Counterpart} - ${entry.Relayer || 'Other'}` // Initialize dataMatrix[label] if it doesn't exist if (!dataMatrix[label]) { diff --git a/src/pages/analytics/components/RelayerChartWithChainSlider.tsx b/src/pages/analytics/components/RelayerChartWithChainSlider.tsx index 08b3a1dd..ef01397d 100644 --- a/src/pages/analytics/components/RelayerChartWithChainSlider.tsx +++ b/src/pages/analytics/components/RelayerChartWithChainSlider.tsx @@ -1,5 +1,5 @@ import { useContext, useEffect, useState } from 'react' -import { bech32PrefixToChainName, formatNumber } from 'utils/commons' +import { formatNumber } from 'utils/commons' import Tooltip from '@mui/material/Tooltip' import Slider from '@mui/material/Slider' import { @@ -57,10 +57,10 @@ export default function RelayerChartWithChainSlider() { } // Sort dates - const sortedDates = Array.from(datesSet).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()) + const sortedDates = Array.from(datesSet).sort() // Sort relayers - const sortedRelayers = Array.from(relayersSet).sort((a, b) => a.localeCompare(b)) + const sortedRelayers = Array.from(relayersSet).sort() // Create datasets for each relayer const datasets = sortedRelayers.map((relayer) => { @@ -84,16 +84,12 @@ export default function RelayerChartWithChainSlider() { // Process data grouped by chain const chainMap: Record = {} - analyticsData4 - .filter((entry: Entry) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret') - .forEach((entry: Entry) => { - const chainBech32Prefix = entry.IBC_Counterpart - const chainName = bech32PrefixToChainName.get(chainBech32Prefix) || chainBech32Prefix - chainMap[chainName] ||= [] - chainMap[chainName].push(entry) - }) + analyticsData4.forEach((entry: Entry) => { + chainMap[entry.IBC_Counterpart] ||= [] + chainMap[entry.IBC_Counterpart].push(entry) + }) - const sortedChains = Object.keys(chainMap).sort((a, b) => a.localeCompare(b)) + const sortedChains = Object.keys(chainMap).sort() setChainLabels(sortedChains) setChainMap(chainMap) diff --git a/src/pages/analytics/components/RelayerChartWithDateSlider.tsx b/src/pages/analytics/components/RelayerChartWithDateSlider.tsx index c2820bea..5c741ca6 100644 --- a/src/pages/analytics/components/RelayerChartWithDateSlider.tsx +++ b/src/pages/analytics/components/RelayerChartWithDateSlider.tsx @@ -1,5 +1,5 @@ import { useContext, useEffect, useState } from 'react' -import { bech32PrefixToChainName, formatNumber } from 'utils/commons' +import { formatNumber } from 'utils/commons' import Tooltip from '@mui/material/Tooltip' import Slider from '@mui/material/Slider' import { @@ -37,13 +37,11 @@ export default function RelayerChartWithDateSlider() { // Process data grouped by date const dateMap: Record = {} - analyticsData4 - .filter((entry: Entry) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret') - .forEach((entry: Entry) => { - const date = new Date(entry.Date).toISOString().split('T')[0] - dateMap[date] ||= [] - dateMap[date].push(entry) - }) + analyticsData4.forEach((entry: Entry) => { + const date = new Date(entry.Date).toISOString().split('T')[0] + dateMap[date] ||= [] + dateMap[date].push(entry) + }) const sortedDates = Object.keys(dateMap).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()) setDates(sortedDates) @@ -80,7 +78,7 @@ export default function RelayerChartWithDateSlider() { // Prepare an array of { prefix, label } pairs const prefixLabelPairs = Array.from(chainsSet).map((prefix) => ({ prefix, - label: bech32PrefixToChainName.get(prefix) || prefix + label: prefix })) // Sort prefixLabelPairs by label alphabetically diff --git a/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx b/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx index c80eb675..8536c204 100644 --- a/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx +++ b/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx @@ -1,5 +1,5 @@ import { useContext, useEffect, useState } from 'react' -import { bech32PrefixToChainName, formatNumber } from 'utils/commons' +import { formatNumber } from 'utils/commons' import Tooltip from '@mui/material/Tooltip' import Slider from '@mui/material/Slider' import { @@ -38,15 +38,13 @@ export default function RelayerChartWithProviderSlider() { // Process data grouped by relayer const relayerMap: Record = {} - analyticsData4 - .filter((entry: Entry) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret') - .forEach((entry: Entry) => { - const relayer = entry.Relayer || 'Other' - relayerMap[relayer] ||= [] - relayerMap[relayer].push(entry) - }) + analyticsData4.forEach((entry: Entry) => { + const relayer = entry.Relayer || 'Other' + relayerMap[relayer] ||= [] + relayerMap[relayer].push(entry) + }) - const sortedRelayers = Object.keys(relayerMap).sort((a, b) => a.localeCompare(b)) + const sortedRelayers = Object.keys(relayerMap).sort() setRelayers(sortedRelayers) // Calculate total transactions per relayer @@ -59,7 +57,7 @@ export default function RelayerChartWithProviderSlider() { const maxTotal = Math.max(...Object.values(relayerTotals)) const topRelayers = Object.keys(relayerTotals).filter((relayer) => relayerTotals[relayer] === maxTotal) // If multiple relayers have the same max total, choose the first one alphabetically - const defaultRelayer = topRelayers.sort((a, b) => a.localeCompare(b))[0] + const defaultRelayer = topRelayers.sort()[0] // Find the index of the default relayer const defaultIndex = sortedRelayers.indexOf(defaultRelayer) @@ -110,7 +108,7 @@ export default function RelayerChartWithProviderSlider() { // Prepare an array of { prefix, label } pairs for chains const prefixLabelPairs = Array.from(chainsSet).map((prefix) => ({ prefix, - label: bech32PrefixToChainName.get(prefix) || prefix + label: prefix })) // Sort prefixLabelPairs by label alphabetically diff --git a/src/utils/commons.ts b/src/utils/commons.ts index e345e00e..80d4a903 100644 --- a/src/utils/commons.ts +++ b/src/utils/commons.ts @@ -22,6 +22,7 @@ export const allTokens = tokens.concat(snips).concat(ICSTokens) // Cache the mapping from bech32 prefixes to chain names export const bech32PrefixToChainName: Map = new Map() + for (const chainInfo of Object.values(chains)) { bech32PrefixToChainName.set(chainInfo.bech32_prefix, chainInfo.chain_name) } From e8dd06d6856fa26f149bf1a0ec29bad210b1bce0 Mon Sep 17 00:00:00 2001 From: alexander-sei <94856309+SecretSaturn@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:59:30 +0100 Subject: [PATCH 3/5] Add Weekly Contract Usage chart --- src/context/APIContext.tsx | 11 + src/pages/analytics/Analytics.tsx | 11 +- .../components/WeeklyContractsChart.tsx | 199 ++++++++++++++++++ 3 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 src/pages/analytics/components/WeeklyContractsChart.tsx diff --git a/src/context/APIContext.tsx b/src/context/APIContext.tsx index 1550e024..5d0a6282 100644 --- a/src/context/APIContext.tsx +++ b/src/context/APIContext.tsx @@ -125,6 +125,7 @@ const APIContextProvider = ({ children }: any) => { const [analyticsData2, setAnalyticsData2] = useState() const [analyticsData3, setAnalyticsData3] = useState() const [analyticsData4, setAnalyticsData4] = useState() + const [analyticsData5, setAnalyticsData5] = useState() const [L5AnalyticsApiData, setL5AnalyticsApiData] = useState() const [volume, setVolume] = useState(Number) const [marketCap, setMarketCap] = useState(Number) @@ -243,6 +244,15 @@ const APIContextProvider = ({ children }: any) => { setAnalyticsData4(filteredData) }) + const API_DATA_SECRET_5 = `https://dashboardstats.secretsaturn.net/source/weekly_contract_usage_stats/data.json` + fetch(API_DATA_SECRET_5) + .catch((error: any) => console.error(error)) + .then((response) => (response as any).json()) + .catch((error: any) => console.error(error)) + .then((response) => { + setAnalyticsData5(response) + }) + const LAVENDERFIVE_API_URL_SECRET_STATUS = `https://api.lavenderfive.com/networks/secretnetwork` fetch(LAVENDERFIVE_API_URL_SECRET_STATUS) .catch((error: any) => console.error(error)) @@ -405,6 +415,7 @@ const APIContextProvider = ({ children }: any) => { analyticsData2, analyticsData3, analyticsData4, + analyticsData5, L5AnalyticsApiData, bondedToken, notBondedToken, diff --git a/src/pages/analytics/Analytics.tsx b/src/pages/analytics/Analytics.tsx index 9c5872e1..2ee1fb82 100644 --- a/src/pages/analytics/Analytics.tsx +++ b/src/pages/analytics/Analytics.tsx @@ -11,9 +11,11 @@ import RelayerChartWithDateSlider from './components/RelayerChartWithDateSlider' import RelayerChartWithChainSlider from './components/RelayerChartWithChainSlider' import RelayerChartWithProviderSlider from './components/RelayerChartWithProviderSlider' import RelayerChartTotal from './components/RelayerChartTotal' +import WeeklyContractsChart from './components/WeeklyContractsChart' function Analytics() { - const { L5AnalyticsApiData, analyticsData1, analyticsData2, analyticsData3, analyticsData4 } = useContext(APIContext) + const { L5AnalyticsApiData, analyticsData1, analyticsData2, analyticsData3, analyticsData4, analyticsData5 } = + useContext(APIContext) useEffect(() => { trackMixPanelEvent('Open Analytics Tab') @@ -65,6 +67,13 @@ function Analytics() { ) : null} + {analyticsData5 ? ( + <> +
+ +
+ + ) : null} {analyticsData4 ? ( <>
diff --git a/src/pages/analytics/components/WeeklyContractsChart.tsx b/src/pages/analytics/components/WeeklyContractsChart.tsx new file mode 100644 index 00000000..521b54a4 --- /dev/null +++ b/src/pages/analytics/components/WeeklyContractsChart.tsx @@ -0,0 +1,199 @@ +import { useContext, useEffect, useState } from 'react' +import { formatNumber } from 'utils/commons' +import { APIContext } from 'context/APIContext' +import Tooltip from '@mui/material/Tooltip' +import { + Chart as ChartJS, + CategoryScale, + LinearScale, + BarElement, + Tooltip as ChartTooltip, + BarController, + Legend, + Title, + ChartOptions, + ChartData, + ChartDataset +} from 'chart.js' +import { Bar } from 'react-chartjs-2' +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' +import { faInfoCircle } from '@fortawesome/free-solid-svg-icons' +import { useUserPreferencesStore } from 'store/UserPreferences' + +ChartJS.register(CategoryScale, LinearScale, BarElement, BarController, ChartTooltip, Legend, Title) + +type Data = { + Date: string + contract_admin: string | null + contract_creator: string | null + contract_name: string + num_transactions: number + num_wallets: number +} + +export default function WeeklyContractsChart() { + const { analyticsData5 } = useContext(APIContext) + const { theme } = useUserPreferencesStore() + const [chartData, setChartData] = useState | null>(null) + + useEffect(() => { + if (analyticsData5) { + // Initialize data structures + const datesSet = new Set() + const contractNamesSet = new Set() + const dataByDateAndContract: Record> = {} + const totalTransactionsPerContract: Record = {} + + // Process analyticsData5 in a single pass + analyticsData5.forEach((item: Data) => { + datesSet.add(item.Date) + contractNamesSet.add(item.contract_name) + + // Accumulate num_transactions per date and contract + if (!dataByDateAndContract[item.Date]) { + dataByDateAndContract[item.Date] = {} + } + if (!dataByDateAndContract[item.Date][item.contract_name]) { + dataByDateAndContract[item.Date][item.contract_name] = 0 + } + dataByDateAndContract[item.Date][item.contract_name] += item.num_transactions + + // Accumulate total num_transactions per contract + if (!totalTransactionsPerContract[item.contract_name]) { + totalTransactionsPerContract[item.contract_name] = 0 + } + totalTransactionsPerContract[item.contract_name] += item.num_transactions + }) + + // Convert sets to arrays and sort dates + const dates = Array.from(datesSet).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()) + const contractNames = Array.from(contractNamesSet) + + // Sort contracts by total transactions and pick top N + const topN = 50 + const sortedContractNames = contractNames.sort( + (a, b) => totalTransactionsPerContract[b] - totalTransactionsPerContract[a] + ) + const topContractNames = sortedContractNames.slice(0, topN) + + // Create datasets for top contracts + const datasets: ChartDataset<'bar', number[]>[] = topContractNames.map((contractName, index) => { + const data = dates.map((date) => dataByDateAndContract[date]?.[contractName] || 0) + return { + label: contractName, + data, + backgroundColor: getColorFromString(contractName), + stack: 'Stack 0' + } + }) + + // Compute 'Others' data + const othersData = dates.map((date) => { + const contractsData = dataByDateAndContract[date] || {} + return Object.entries(contractsData).reduce((total, [name, value]) => { + return topContractNames.includes(name) ? total : total + value + }, 0) + }) + + // Add 'Others' dataset if applicable + if (othersData.some((value) => value > 0)) { + datasets.push({ + label: 'Others', + data: othersData, + backgroundColor: '#cccccc', + stack: 'Stack 0' + }) + } + + // Prepare chart data + const preparedChartData: ChartData<'bar', number[], string> = { + labels: dates.map((date) => + new Date(date).toLocaleDateString(undefined, { + year: '2-digit', + month: '2-digit', + day: '2-digit' + }) + ), + datasets + } + + setChartData(preparedChartData) + } + }, [analyticsData5, theme]) + + function getColorFromString(str: string) { + // Generate a unique color based on the combo string + let hash = 0 + for (let i = 0; i < str.length; i++) { + hash = str.charCodeAt(i) + ((hash << 5) - hash) + } + const color = `#${('000000' + (hash & 0xffffff).toString(16)).slice(-6)}` + return color + } + + const options: ChartOptions<'bar'> = { + responsive: true, + animation: true, + maintainAspectRatio: false, + scales: { + x: { + stacked: true, + ticks: { + color: theme === 'dark' ? '#fff' : '#000', + autoSkip: false, + maxRotation: 90, + minRotation: 45 + }, + grid: { + display: false + } + }, + y: { + beginAtZero: true, + stacked: true, + ticks: { + color: theme === 'dark' ? '#fff' : '#000', + callback: (value: number | string) => formatNumber(value, 2) + }, + grid: { + color: theme === 'dark' ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)', + display: true + } + } + }, + plugins: { + legend: { + display: false + }, + tooltip: { + xAlign: 'center', + yAlign: 'bottom', + backgroundColor: theme === 'dark' ? '#333' : '#fff', + titleColor: theme === 'dark' ? '#fff' : '#000', + bodyColor: theme === 'dark' ? '#fff' : '#000' + } + } + } + + return ( + <> +
+

+ Weekly Transactions per Contract +
+ + + + + +
+

+
+
+ {chartData && chartData.datasets && chartData.datasets.length > 0 ? ( + + ) : null} +
+ + ) +} From 60ac67fbcb27fed13887e3e030f64e4ca9a4cf13 Mon Sep 17 00:00:00 2001 From: alexander-sei <94856309+SecretSaturn@users.noreply.github.com> Date: Mon, 11 Nov 2024 19:03:36 +0100 Subject: [PATCH 4/5] Fix build --- src/pages/analytics/components/WeeklyContractsChart.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/analytics/components/WeeklyContractsChart.tsx b/src/pages/analytics/components/WeeklyContractsChart.tsx index 521b54a4..7ed62454 100644 --- a/src/pages/analytics/components/WeeklyContractsChart.tsx +++ b/src/pages/analytics/components/WeeklyContractsChart.tsx @@ -131,7 +131,7 @@ export default function WeeklyContractsChart() { return color } - const options: ChartOptions<'bar'> = { + const options = { responsive: true, animation: true, maintainAspectRatio: false, @@ -153,7 +153,7 @@ export default function WeeklyContractsChart() { stacked: true, ticks: { color: theme === 'dark' ? '#fff' : '#000', - callback: (value: number | string) => formatNumber(value, 2) + callback: (value: number) => formatNumber(value, 2) }, grid: { color: theme === 'dark' ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)', @@ -191,7 +191,7 @@ export default function WeeklyContractsChart() {
{chartData && chartData.datasets && chartData.datasets.length > 0 ? ( - + ) : null}
From 53eef2de5948aa98ebba243b1e363396d897b3b2 Mon Sep 17 00:00:00 2001 From: alexander-sei <94856309+SecretSaturn@users.noreply.github.com> Date: Mon, 11 Nov 2024 20:28:38 +0100 Subject: [PATCH 5/5] Relayer chart performance improvements --- .../components/RelayerChartWithDateSlider.tsx | 16 +++----------- .../RelayerChartWithProviderSlider.tsx | 22 +++++-------------- 2 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/pages/analytics/components/RelayerChartWithDateSlider.tsx b/src/pages/analytics/components/RelayerChartWithDateSlider.tsx index 5c741ca6..2a5330d8 100644 --- a/src/pages/analytics/components/RelayerChartWithDateSlider.tsx +++ b/src/pages/analytics/components/RelayerChartWithDateSlider.tsx @@ -75,23 +75,13 @@ export default function RelayerChartWithDateSlider() { chainMap.set(chainBech32Prefix, (chainMap.get(chainBech32Prefix) || 0) + entry.Transactions) } - // Prepare an array of { prefix, label } pairs - const prefixLabelPairs = Array.from(chainsSet).map((prefix) => ({ - prefix, - label: prefix - })) - - // Sort prefixLabelPairs by label alphabetically - prefixLabelPairs.sort((a, b) => a.label.localeCompare(b.label)) - - // Extract the sorted bech32Prefixes and labels - const sortedBech32Prefixes = prefixLabelPairs.map((pair) => pair.prefix) - const labels = prefixLabelPairs.map((pair) => pair.label) + // Sort the prefixes alphabetically and use them as labels + const labels = Array.from(chainsSet).sort() // Create datasets for each relayer const datasets = Array.from(relayersSet).map((relayer) => { const chainMap = dataMatrix.get(relayer)! - const data = sortedBech32Prefixes.map((prefix) => chainMap.get(prefix) || 0) + const data = labels.map((prefix) => chainMap.get(prefix) || 0) return { label: relayer, data, diff --git a/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx b/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx index 8536c204..cd6b6972 100644 --- a/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx +++ b/src/pages/analytics/components/RelayerChartWithProviderSlider.tsx @@ -102,30 +102,18 @@ export default function RelayerChartWithProviderSlider() { dateMap.set(date, (dateMap.get(date) || 0) + entry.Transactions) } - // Sort dates + // Sort dates and chains const sortedDates = Array.from(datesSet).sort((a, b) => new Date(a).getTime() - new Date(b).getTime()) - - // Prepare an array of { prefix, label } pairs for chains - const prefixLabelPairs = Array.from(chainsSet).map((prefix) => ({ - prefix, - label: prefix - })) - - // Sort prefixLabelPairs by label alphabetically - prefixLabelPairs.sort((a, b) => a.label.localeCompare(b.label)) - - // Extract the sorted bech32Prefixes and labels - const sortedBech32Prefixes = prefixLabelPairs.map((pair) => pair.prefix) - const chainLabels = prefixLabelPairs.map((pair) => pair.label) + const sortedChains = Array.from(chainsSet).sort((a, b) => a.localeCompare(b)) // Create datasets for each chain - const datasets = sortedBech32Prefixes.map((chainPrefix, index) => { + const datasets = sortedChains.map((chainPrefix) => { const dateMap = dataMatrix.get(chainPrefix)! const data = sortedDates.map((date) => dateMap.get(date) || 0) return { - label: chainLabels[index], + label: chainPrefix, data, - backgroundColor: getColorFromChain(chainLabels[index]) + backgroundColor: getColorFromChain(chainPrefix) } })