diff --git a/src/App.js b/src/App.js
index d246157..df52849 100644
--- a/src/App.js
+++ b/src/App.js
@@ -4,7 +4,8 @@ import Startup from './pages/loadingScreen.js';
import Grafana from './pages/grafana.js';
import Livepeer from './pages/livepeer.js';
import Stats from './pages/stats.js';
-import Summary from './pages/summary.js'
+import Summary from './pages/summary.js';
+import Graphs from './pages/graph.js';
import {
BrowserRouter as Router,
@@ -22,6 +23,7 @@ export default function App() {
} />
} />
} />
+ } />
} />
} />
diff --git a/src/components/CommissionGraph.js b/src/components/CommissionGraph.js
new file mode 100644
index 0000000..387b811
--- /dev/null
+++ b/src/components/CommissionGraph.js
@@ -0,0 +1,14 @@
+import React, { useState } from 'react';
+import { useSelector } from 'react-redux';
+
+const CommissionGraph = (obj) => {
+
+
+ return (
+
+
+
+ )
+}
+
+export default CommissionGraph;
\ No newline at end of file
diff --git a/src/components/MonthlyOrchestrators.js b/src/components/MonthlyOrchestrators.js
index ac53b5d..1d065a8 100644
--- a/src/components/MonthlyOrchestrators.js
+++ b/src/components/MonthlyOrchestrators.js
@@ -10,7 +10,6 @@ import { Pagination } from "@mantine/core";
const itemsPerPage = 10;
const MonthlyOrchestrators = (obj) => {
- const livepeer = useSelector((state) => state.livepeerstate);
const [thisScores, setThisScores] = useState(null);
const [activePage, setPage] = useState(1);
diff --git a/src/components/TotalStakeGraph.js b/src/components/TotalStakeGraph.js
new file mode 100644
index 0000000..474a773
--- /dev/null
+++ b/src/components/TotalStakeGraph.js
@@ -0,0 +1,163 @@
+import React, { useState } from 'react';
+import { useSelector } from 'react-redux';
+import { VictoryLine, VictoryChart, VictoryLegend } from 'victory';
+
+const TotalStakeGraph = (obj) => {
+ const livepeer = useSelector((state) => state.livepeerstate);
+
+ const getName = (address) => {
+ let thisDomain = null;
+ // Lookup domain in cache
+ if (livepeer.ensDomainMapping) {
+ for (const thisAddr of livepeer.ensDomainMapping) {
+ if (thisAddr.address === address) {
+ thisDomain = thisAddr;
+ break;
+ }
+ }
+ }
+ // Lookup current info in cache only if this addr has a mapped ENS domain
+ if (thisDomain && thisDomain.domain) {
+ for (const thisAddr of livepeer.ensInfoMapping) {
+ if (thisAddr.domain === thisDomain.domain) {
+ if (thisAddr.domain.length > 18) {
+ return (thisAddr.domain.substring(0, 16) + "..");
+ }
+ return thisAddr.domain;
+ }
+ }
+ }
+
+ if (livepeer.threeBoxInfo) {
+ for (const thisAddr of livepeer.threeBoxInfo) {
+ if (thisAddr.address === address) {
+ if (thisAddr.name) {
+ if (thisAddr.name.length > 18) {
+ return (thisAddr.name.substring(0, 16) + "..");
+ }
+ return thisAddr.name;
+ } else {
+ return (address.substring(0, 16) + "..");
+ }
+ break;
+ }
+ }
+ }
+
+ return (address.substring(0, 16) + "..");
+ }
+
+ const colors = [
+ "#282678",
+ "#56256c",
+ "#872974",
+ "#b63074",
+ "#de416d",
+ "#ff5c5f",
+ "#ffe085",
+ "#f0e575",
+ "#daec69",
+ "#bef262",
+ "#97f964",
+ "#5cff6f",
+ "#14ff47",
+ "#00fb94",
+ "#00f3cd",
+ "#00e7f3",
+ "#00d8ff",
+ "#24c8ff",
+ "#0a78ff",
+ "#5864d7",
+ "#6952b1",
+ "#69448d",
+ "#61386c",
+ "#522f50"
+ ]
+ let listOfNames = [];
+ let listOfLists = [];
+ let listToParse = [...obj.data];
+
+ // Turn unprocessed list into a per orchestrator list
+ while (listToParse.length) {
+ // Take first orchestrator as the current orchestrator
+ const currentOrchestrator = listToParse[0].address;
+ let thisIdx = listToParse.length - 1;
+ let curData = [];
+ // Split of all orchestrators
+ while (thisIdx >= 0) {
+ const cur = listToParse[thisIdx];
+ if (cur.address == currentOrchestrator) {
+ const thisDate = new Date(cur.timestamp);
+ curData.push({
+ x: thisDate,
+ y: cur.totalStake.toFixed(0)
+ });
+ listToParse.splice(thisIdx, 1);
+ }
+ thisIdx--;
+ }
+ if (curData.length) {
+ listOfNames.push(currentOrchestrator);
+ listOfLists.push(curData);
+ }
+ }
+
+ let legendData = [];
+
+ return (
+
+
+
+
Total stake over time
+
+ {listOfLists.map((thisData, thisIndex) => {
+ if (thisIndex < 100) {
+ legendData.push({ name: getName(listOfNames[thisIndex]), symbol: { fill: colors[thisIndex % colors.length] } });
+ return (
+
+ )
+ } else {
+ return null;
+ }
+ })}
+
+
+
+
+
+
+
+ )
+}
+
+export default TotalStakeGraph;
\ No newline at end of file
diff --git a/src/pages/graph.js b/src/pages/graph.js
new file mode 100644
index 0000000..68ba1ae
--- /dev/null
+++ b/src/pages/graph.js
@@ -0,0 +1,164 @@
+import React, { useState } from 'react'
+import '../style.css';
+import { Navigate } from "react-router-dom";
+import { useSelector } from 'react-redux';
+import { SegmentedControl } from "@mantine/core";
+import CommissionGraph from '../components/CommissionGraph';
+import TotalStakeGraph from '../components/TotalStakeGraph';
+
+
+const Graphs = (obj) => {
+ const livepeer = useSelector((state) => state.livepeerstate);
+ const [redirectToHome, setRedirectToHome] = useState(false);
+ const [showOnlyTranscoders, setShowOnlyTranscoders] = useState(true);
+ const [activePage, setPage] = useState(1);
+
+ let thisColour;
+ if (activePage == 1) {
+ thisColour = "teal";
+ } else if (activePage == 2) {
+ thisColour = "indigo";
+ } else if (activePage == 3) {
+ thisColour = "gray";
+ }
+ console.log("Rendering Graphs Viewer");
+
+ if (redirectToHome) {
+ return ;
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ {
+ activePage == 1 ?
: null
+ }
+ {
+ activePage == 2 ?
: null
+ }
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export default Graphs;
\ No newline at end of file
diff --git a/src/pages/home.js b/src/pages/home.js
index 111dfb6..29b0c75 100644
--- a/src/pages/home.js
+++ b/src/pages/home.js
@@ -15,6 +15,7 @@ const Home = (obj) => {
const [redirectToGrafana, setRedirectToGrafana] = useState(false);
const [redirectToLPT, setRedirectToLPT] = useState(false);
const [redirectToStats, setRedirectToStats] = useState(false);
+ const [redirectToGraphs, setRedirectToGraphs] = useState(false);
if (redirectToGrafana) {
return ;
}
@@ -24,6 +25,10 @@ const Home = (obj) => {
if (redirectToStats) {
return ;
}
+
+ if (redirectToGraphs) {
+ return ;
+ }
// Get amount of unique IP's which have visited this website
var totalVisitorCount = 0;
if (userstate.visitorStats) {
@@ -38,7 +43,7 @@ const Home = (obj) => {
-
+
Home
@@ -71,11 +76,25 @@ const Home = (obj) => {
📈 Statistics 💰
+
+
{
+ setRedirectToGraphs(true);
+ }}>
+ 📉 Graphs 📊
+
+
+
+
Status
+
+
+
Currently there is an issue with Events getting duplicated. The website will have inflated statistics and become unavailable from time to time while we are working on a fix
+
+