Skip to content

Commit

Permalink
Merge pull request #185 from scrtlabs/More-Relayer-Stats
Browse files Browse the repository at this point in the history
Add combined chart for relayer
  • Loading branch information
SecretSaturn authored Oct 27, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents 9e93c43 + f9eba8a commit ec9c7e0
Showing 5 changed files with 202 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/pages/analytics/Analytics.tsx
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ import TransactionsChart from './components/TransactionsChart'
import RelayerChartWithDateSlider from './components/RelayerChartWithDateSlider'
import RelayerChartWithChainSlider from './components/RelayerChartWithChainSlider'
import RelayerChartWithProviderSlider from './components/RelayerChartWithProviderSlider'
import RelayerChartTotal from './components/RelayerChartTotal'

function Analytics() {
const { L5AnalyticsApiData, analyticsData1, analyticsData2, analyticsData3, analyticsData4 } = useContext(APIContext)
@@ -68,6 +69,9 @@ function Analytics() {
<>
<div className="col-span-12 rounded-xl bg-white border border-neutral-200 dark:border-neutral-700 dark:bg-neutral-800">
<div className="flex flex-col">
<div className="border-b border-neutral-200 dark:border-neutral-700 p-4">
<RelayerChartTotal />
</div>
<div className="border-b border-neutral-200 dark:border-neutral-700 p-4">
<RelayerChartWithDateSlider />
</div>
194 changes: 194 additions & 0 deletions src/pages/analytics/components/RelayerChartTotal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
import { useContext, useMemo } from 'react'
import { bech32PrefixToChainName, formatNumber } from 'utils/commons'
import Tooltip from '@mui/material/Tooltip'
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
BarElement,
Tooltip as ChartTooltip,
Legend,
BarController
} 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'
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)

const chartData = useMemo(() => {
if (!analyticsData4) return null

const datesSet = new Set<string>()
const dataMatrix: Record<string, number[]> = {}

const filteredData = analyticsData4.filter(
(entry: Entry) => entry.IBC_Counterpart !== null && entry.IBC_Counterpart !== 'secret'
)

// Collect and sort dates
for (const entry of filteredData) {
const date = new Date(entry.Date).toISOString().split('T')[0]
datesSet.add(date)
}
const sortedDates = Array.from(datesSet).sort()

// Create a date-to-index map
const dateIndexMap = sortedDates.reduce(
(acc, date, index) => {
acc[date] = index
return acc
},
{} as Record<string, number>
)

// Process entries and populate dataMatrix
for (const entry of filteredData) {
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'
}`

// Initialize dataMatrix[label] if it doesn't exist
if (!dataMatrix[label]) {
dataMatrix[label] = new Array(sortedDates.length).fill(0)
}

// Update the corresponding value
dataMatrix[label][dateIndex] += entry.Transactions
}

// Create datasets without nested mapping
const datasets = Object.keys(dataMatrix).map((label) => ({
label,
data: dataMatrix[label],
backgroundColor: getColorFromCombo(label)
}))

// Return the final chart data
return {
labels: sortedDates,
datasets
}
}, [analyticsData4])

const options = useMemo(() => {
if (!chartData) return {}

return {
responsive: true,
animation: true,
maintainAspectRatio: false,
scales: {
x: {
stacked: true,
ticks: {
color: theme === 'dark' ? '#fff' : '#000',
callback: function (value: any, index: number) {
return new Date((chartData as any).labels[index]).toLocaleDateString(undefined, {
year: '2-digit',
month: '2-digit',
day: '2-digit'
})
}
},
grid: {
color: theme === 'dark' ? '#fff' : '#000',
alpha: 0.5,
display: false,
drawOnChartArea: true,
drawTicks: true,
tickLength: 0
},
border: {
color: theme === 'dark' ? '#fff' : '#000'
}
},
y: {
beginAtZero: true,
stacked: true,
ticks: {
color: theme === 'dark' ? '#fff' : '#000',
callback: function (value: any) {
return formatNumber(value, 2)
}
},
border: {
color: theme === 'dark' ? '#fff' : '#000'
},
grid: {
color: theme === 'dark' ? 'rgba(255, 255, 255, 0.2)' : 'rgba(0, 0, 0, 0.2)',
display: true,
drawOnChartArea: true,
drawTicks: true,
tickLength: 0
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
xAlign: 'center',
color: theme === 'dark' ? '#fff' : '#000',
callbacks: {
label: function (context: any) {
if (context.parsed.y !== null) {
return `${context.dataset.label}: ${formatNumber(context.parsed.y)} Transactions`
}
return ''
}
}
}
}
}
}, [theme, chartData])

function getColorFromCombo(combo: string) {
// Generate a unique color based on the combo string
let hash = 0
for (let i = 0; i < combo.length; i++) {
hash = combo.charCodeAt(i) + ((hash << 5) - hash)
}
const color = `#${('000000' + (hash & 0xffffff).toString(16)).slice(-6)}`
return color
}

return (
<>
<div>
<h2 className="text-center text-xl font-semibold pt-2.5 pb-0">
IBC Transactions
<Tooltip
title="Chart shows the IBC transactions per date for each combination of chain and relayer."
placement="right"
arrow
>
<span className="text-neutral-600 dark:text-neutral-400 hover:text-black dark:hover:text-white transition-colors cursor-pointer ml-2 text-sm">
<FontAwesomeIcon icon={faInfoCircle} />
</span>
</Tooltip>
</h2>
</div>
<div className="w-full h-[300px] xl:h-[400px]">
{chartData ? <Bar data={chartData} options={options as any} /> : null}
</div>
</>
)
}
Original file line number Diff line number Diff line change
@@ -208,7 +208,7 @@ export default function RelayerChartWithChainSlider() {
for (let i = 0; i < relayer.length; i++) {
hash = relayer.charCodeAt(i) + ((hash << 5) - hash)
}
const color = `#${(hash & 0x00ffffff).toString(16).padStart(6, '0').slice(-6)}`
const color = `#${('000000' + (hash & 0xffffff).toString(16)).slice(-6)}`
return color
}

@@ -218,7 +218,7 @@ export default function RelayerChartWithChainSlider() {
<h2 className="text-center text-xl font-semibold pt-2.5 pb-0">
{`IBC Transactions by Date and Relayer for ${chainLabels[selectedChainIndex]}`}
<Tooltip
title="Use the slider to select a chain and view transactions by date and relayer."
title="Use the slider to select a chain, the chart then shows the IBC transactions per date for each relayer."
placement="right"
arrow
>
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'
import { useUserPreferencesStore } from 'store/UserPreferences'
import { APIContext } from 'context/APIContext'
import { chains } from 'utils/config'

ChartJS.register(CategoryScale, LinearScale, BarElement, ChartTooltip, Legend, BarController)

@@ -230,7 +229,7 @@ export default function RelayerChartWithDateSlider() {
for (let i = 0; i < relayer.length; i++) {
hash = relayer.charCodeAt(i) + ((hash << 5) - hash)
}
const color = `#${(hash & 0x00ffffff).toString(16).padStart(6, '0').slice(-6)}`
const color = `#${('000000' + (hash & 0xffffff).toString(16)).slice(-6)}`
return color
}

Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons'
import { useUserPreferencesStore } from 'store/UserPreferences'
import { APIContext } from 'context/APIContext'
import { chains } from 'utils/config'

ChartJS.register(CategoryScale, LinearScale, BarElement, ChartTooltip, Legend, BarController)

@@ -224,7 +223,7 @@ export default function RelayerChartWithProviderSlider() {
for (let i = 0; i < chain.length; i++) {
hash = chain.charCodeAt(i) + ((hash << 5) - hash)
}
const color = `#${(hash & 0x00ffffff).toString(16).padStart(6, '0').slice(-6)}`
const color = `#${('000000' + (hash & 0xffffff).toString(16)).slice(-6)}`
return color
}

0 comments on commit ec9c7e0

Please sign in to comment.