mirror of
https://github.com/stronk-dev/LivepeerEvents.git
synced 2025-07-05 10:45:10 +02:00
Slighly better stake overview
This commit is contained in:
parent
bf708e83c2
commit
124c81bce7
203
src/components/StakeOverview.js
Normal file
203
src/components/StakeOverview.js
Normal file
@ -0,0 +1,203 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { VictoryPie } from 'victory';
|
||||
import Address from '../components/OrchAddressViewer';
|
||||
import {
|
||||
getOrchestratorScores
|
||||
} from "../actions/livepeer";
|
||||
|
||||
const StakeOverview = (obj) => {
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const dispatch = useDispatch();
|
||||
const [thisScores, setThisScores] = useState(null);
|
||||
const [removeOnlyStakers, setRemoveOnlyStakers] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const now = new Date().getTime();
|
||||
let wasInCache = false;
|
||||
// See if it is cached
|
||||
for (const thisScore of livepeer.orchScores) {
|
||||
if (thisScore.year === obj.year && thisScore.month === obj.month) {
|
||||
// Check timeout
|
||||
if (now - thisScore.timestamp < 360000) {
|
||||
wasInCache = true;
|
||||
}
|
||||
if (!thisScores) {
|
||||
setThisScores(thisScore);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!wasInCache) {
|
||||
dispatch(getOrchestratorScores(obj.year, obj.month));
|
||||
}
|
||||
}, [livepeer.orchScores]);
|
||||
|
||||
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) {
|
||||
return thisAddr.domain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (livepeer.threeBoxInfo) {
|
||||
for (const thisAddr of livepeer.threeBoxInfo) {
|
||||
if (thisAddr.address === address) {
|
||||
if (thisAddr.name) {
|
||||
return thisAddr.name;
|
||||
} else {
|
||||
return (address.substring(0, 10) + "..");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (address.substring(0, 10) + "..");
|
||||
}
|
||||
|
||||
let orchList = [];
|
||||
let pieList = [];
|
||||
let otherSum = 0;
|
||||
let pieObj = null;
|
||||
if (livepeer.orchInfo) {
|
||||
let orchIdx = livepeer.orchInfo.length - 1;
|
||||
// calc sum of stake
|
||||
let totalStake = 0;
|
||||
while (orchIdx >= 0) {
|
||||
const thisOrch = livepeer.orchInfo[orchIdx];
|
||||
orchIdx -= 1;
|
||||
if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) {
|
||||
continue;
|
||||
}
|
||||
totalStake += parseInt(thisOrch.totalStake);
|
||||
}
|
||||
// create slices
|
||||
orchIdx = livepeer.orchInfo.length - 1;
|
||||
while (orchIdx >= 0) {
|
||||
const thisOrch = livepeer.orchInfo[orchIdx];
|
||||
const thisStake = parseInt(thisOrch.totalStake);
|
||||
orchIdx -= 1;
|
||||
if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) {
|
||||
continue;
|
||||
}
|
||||
// Add orch stat descending
|
||||
let idx = orchList.length - 1;
|
||||
while (idx >= 0) {
|
||||
const sel = orchList[idx];
|
||||
idx--;
|
||||
if (sel.sum < thisStake) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (idx == orchList.length - 1) {
|
||||
orchList.push({
|
||||
address: thisOrch.id,
|
||||
sum: thisStake,
|
||||
ratio: (thisStake / totalStake) * 100
|
||||
});
|
||||
} else {
|
||||
orchList.splice(idx + 1, 0, {
|
||||
address: thisOrch.id,
|
||||
sum: thisStake,
|
||||
ratio: (thisStake / totalStake) * 100
|
||||
});
|
||||
}
|
||||
// Add slice
|
||||
if ((thisStake / totalStake) < 0.04) {
|
||||
otherSum += thisStake;
|
||||
} else {
|
||||
pieList.push({
|
||||
address: getName(thisOrch.id),
|
||||
sum: thisStake
|
||||
});
|
||||
}
|
||||
}
|
||||
pieList.push({
|
||||
address: "Other",
|
||||
sum: otherSum
|
||||
});
|
||||
pieObj = <div className="stroke">
|
||||
<h4>Active Orchestrators by Stake</h4>
|
||||
<div className='row'>
|
||||
<p>Only Transcoding?</p>
|
||||
<div className="toggle-container" onClick={() => setRemoveOnlyStakers(!removeOnlyStakers)}>
|
||||
<div className={`dialog-button ${removeOnlyStakers ? "" : "disabled"}`}>
|
||||
{removeOnlyStakers ? "1" : "0"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<VictoryPie padding={100} data={pieList} x="address" y="sum"
|
||||
sortOrder="descending"
|
||||
sortKey="sum"
|
||||
colorScale={[
|
||||
"#003f5c",
|
||||
"#2f4b7c",
|
||||
"#665191",
|
||||
"#ff7c43",
|
||||
"#ffa600",
|
||||
"#5c3446",
|
||||
"#83424e",
|
||||
"#a6544e",
|
||||
"#c16d46",
|
||||
"#d18d3c",
|
||||
"#d3b136",
|
||||
"#c5d843",
|
||||
"#a3ff69",
|
||||
]}
|
||||
style={{
|
||||
data: {
|
||||
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
|
||||
},
|
||||
labels: {
|
||||
fontSize: 10, zIndex: 999
|
||||
}
|
||||
}} />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
return (
|
||||
<div className="stroke">
|
||||
{pieObj}
|
||||
<div className="flexContainer forceWrap">
|
||||
{
|
||||
orchList.map(function (orch) {
|
||||
return (
|
||||
<div className="row" key={"staker" + orch.address + orch.sum}>
|
||||
<div className="rowAlignLeft">
|
||||
<Address address={orch.address} seed={"stake" + orch.address + orch.sum} />
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
|
||||
<div className="rowAlignLeft" >
|
||||
<h4>{orch.sum.toFixed(2)} LPT</h4>
|
||||
</div>
|
||||
<div className="rowAlignRight" >
|
||||
<span>({orch.ratio.toFixed(2)} %)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
<div className="verticalDivider" />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default StakeOverview;
|
@ -8,16 +8,15 @@ const EventButtonAddress = (obj) => {
|
||||
const dispatch = useDispatch();
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const [hasRefreshed, setRefresh] = useState(false);
|
||||
const [hasENS, setHasENS] = useState(false);
|
||||
const [hasThreeBox, setHasThreeBox] = useState(false);
|
||||
const [hasThreeBoxRefreshed, setThreeBoxRefresh] = useState(false);
|
||||
const [hasOrchInfo, setHasOrchInfo] = useState(false);
|
||||
const [orchInfo, setOrchInfo] = useState(null);
|
||||
const now = new Date().getTime();
|
||||
|
||||
useEffect(() => {
|
||||
let thisInfo = null;
|
||||
let thisDomain = null;
|
||||
let hasENS = null;
|
||||
let hasThreeBox = null
|
||||
// Lookup domain in cache
|
||||
if (livepeer.ensDomainMapping && !hasRefreshed) {
|
||||
for (const thisAddr of livepeer.ensDomainMapping) {
|
||||
@ -29,6 +28,7 @@ const EventButtonAddress = (obj) => {
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
console.log("Refresh due to old ENS domain");
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
@ -37,6 +37,7 @@ const EventButtonAddress = (obj) => {
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisDomain == null && !hasRefreshed) {
|
||||
console.log("Refresh due to non-existing ENS domain");
|
||||
setRefresh(true);
|
||||
getEnsInfo(obj.address);
|
||||
}
|
||||
@ -46,13 +47,14 @@ const EventButtonAddress = (obj) => {
|
||||
for (const thisAddr of livepeer.ensInfoMapping) {
|
||||
if (thisAddr.domain === thisDomain.domain) {
|
||||
thisInfo = thisAddr;
|
||||
setHasENS(true);
|
||||
hasENS = true;
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
console.log("Refresh due to old ENS info");
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
@ -61,6 +63,7 @@ const EventButtonAddress = (obj) => {
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisInfo == null && !hasRefreshed) {
|
||||
console.log("Refresh due to non-existing ENS info");
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
@ -72,51 +75,41 @@ const EventButtonAddress = (obj) => {
|
||||
for (const thisAddr of livepeer.threeBoxInfo) {
|
||||
if (thisAddr.address === obj.address) {
|
||||
thisInfo = thisAddr;
|
||||
setHasThreeBox(true);
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasThreeBoxRefreshed) {
|
||||
getThreeBoxInfo(obj.address);
|
||||
setThreeBoxRefresh(true);
|
||||
}
|
||||
hasThreeBox = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisDomain == null && !hasThreeBoxRefreshed) {
|
||||
if (!hasThreeBox && !hasThreeBoxRefreshed) {
|
||||
console.log("Refresh due to non-existing 3BOX info");
|
||||
setThreeBoxRefresh(true);
|
||||
getThreeBoxInfo(obj.address);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (thisInfo && thisInfo != orchInfo){
|
||||
console.log("Setting INFO obj");
|
||||
setOrchInfo(thisInfo);
|
||||
}
|
||||
}, [livepeer.ensDomainMapping, livepeer.threeBoxInfo, hasRefreshed, hasENS, hasThreeBoxRefreshed]);
|
||||
}, [livepeer.ensDomainMapping, livepeer.threeBoxInfo]);
|
||||
|
||||
useEffect(() => {
|
||||
// Check if cached as an orchestrator
|
||||
if (livepeer.orchInfo && !hasOrchInfo) {
|
||||
if (livepeer.orchInfo) {
|
||||
for (const thisOrch of livepeer.orchInfo) {
|
||||
if (thisOrch.id === obj.address) {
|
||||
setHasOrchInfo(true);
|
||||
break;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Preload Orch info
|
||||
if (!hasOrchInfo) {
|
||||
console.log("Refresh due to non-existing orch in global state");
|
||||
dispatch(getOrchestratorInfoSilent(obj.address));
|
||||
setHasOrchInfo(true);
|
||||
}
|
||||
}
|
||||
}, [livepeer.orchInfo, hasOrchInfo]);
|
||||
}, [livepeer.orchInfo]);
|
||||
|
||||
let thisName;
|
||||
let thisIcon;
|
||||
if (hasENS) {
|
||||
if (orchInfo && orchInfo.domain) {
|
||||
thisName = <h4 className="elipsText elipsOnMobileExtra">{orchInfo.domain}</h4>;
|
||||
if (orchInfo.avatar) {
|
||||
thisIcon =
|
||||
@ -124,7 +117,7 @@ const EventButtonAddress = (obj) => {
|
||||
<img alt="" src={orchInfo.avatar.url} width="20em" height="20em" style={{ margin: 0, padding: 0 }} />
|
||||
</a >
|
||||
}
|
||||
} else if (hasThreeBox) {
|
||||
} else if (orchInfo && (orchInfo.name || orchInfo.image)) {
|
||||
if (orchInfo.name) {
|
||||
thisName = <h4 className="elipsText elipsOnMobileExtra">{orchInfo.name}</h4>;
|
||||
} else {
|
||||
|
@ -5,13 +5,13 @@ import { useSelector, useDispatch } from 'react-redux';
|
||||
import { Accordion } from '@mantine/core';
|
||||
import ScrollContainer from 'react-indiana-drag-scroll';
|
||||
import WinnerMonth from '../components/WinnerMonth';
|
||||
import StakeOverview from '../components/StakeOverview';
|
||||
import { VictoryPie } from 'victory';
|
||||
|
||||
const Tickets = (obj) => {
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const [ticketsPerMonth, setTicketsPerMonth] = useState([]);
|
||||
const [redirectToHome, setRedirectToHome] = useState(false);
|
||||
const [removeOnlyStakers, setRemoveOnlyStakers] = useState(false);
|
||||
|
||||
console.log("Rendering Winning Ticket Viewer");
|
||||
|
||||
@ -176,81 +176,6 @@ const Tickets = (obj) => {
|
||||
return (address.substring(0, 10) + "..");
|
||||
}
|
||||
|
||||
let pieList = [];
|
||||
let otherSum = 0;
|
||||
let pieObj = null;
|
||||
if (livepeer.orchInfo) {
|
||||
let orchIdx = livepeer.orchInfo.length - 1;
|
||||
// calc sum of stake
|
||||
let totalStake = 0;
|
||||
while (orchIdx >= 0) {
|
||||
const thisOrch = livepeer.orchInfo[orchIdx];
|
||||
orchIdx -= 1;
|
||||
if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) {
|
||||
continue;
|
||||
}
|
||||
totalStake += parseInt(thisOrch.totalStake);
|
||||
}
|
||||
// create slices
|
||||
orchIdx = livepeer.orchInfo.length - 1;
|
||||
while (orchIdx >= 0) {
|
||||
const thisOrch = livepeer.orchInfo[orchIdx];
|
||||
orchIdx -= 1;
|
||||
if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) {
|
||||
continue;
|
||||
}
|
||||
if ((thisOrch.totalStake / totalStake) < 0.04) {
|
||||
otherSum += thisOrch.totalStake;
|
||||
} else {
|
||||
pieList.push({
|
||||
address: getName(thisOrch.id),
|
||||
sum: thisOrch.totalStake
|
||||
});
|
||||
}
|
||||
}
|
||||
pieList.push({
|
||||
address: "Other",
|
||||
sum: otherSum
|
||||
});
|
||||
pieObj = <div className="stroke">
|
||||
<h4>Active Orchestrators by Stake</h4>
|
||||
<div className='row'>
|
||||
<p>Show non-transcoding Orchestrators?</p>
|
||||
<div className="toggle-container" onClick={() => setRemoveOnlyStakers(!removeOnlyStakers)}>
|
||||
<div className={`dialog-button ${removeOnlyStakers ? "" : "disabled"}`}>
|
||||
{removeOnlyStakers ? "Show" : "Hide"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<VictoryPie padding={100} data={pieList} x="address" y="sum"
|
||||
sortOrder="descending"
|
||||
sortKey="sum"
|
||||
colorScale={[
|
||||
"#003f5c",
|
||||
"#2f4b7c",
|
||||
"#665191",
|
||||
"#ff7c43",
|
||||
"#ffa600",
|
||||
"#5c3446",
|
||||
"#83424e",
|
||||
"#a6544e",
|
||||
"#c16d46",
|
||||
"#d18d3c",
|
||||
"#d3b136",
|
||||
"#c5d843",
|
||||
"#a3ff69",
|
||||
]}
|
||||
style={{
|
||||
data: {
|
||||
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
|
||||
},
|
||||
labels: {
|
||||
fontSize: 10, zIndex: 999
|
||||
}
|
||||
}} />
|
||||
</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ margin: 0, padding: 0, height: '100%', width: '100%', overflow: 'hidden' }}>
|
||||
<div id='header'>
|
||||
@ -272,7 +197,6 @@ const Tickets = (obj) => {
|
||||
<ScrollContainer activationDistance={1} className="overflow-container" hideScrollbars={false}>
|
||||
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}>
|
||||
<div className="flexContainer forceWrap" >
|
||||
{pieObj}
|
||||
<Accordion initialItem={0} className="stroke"
|
||||
styles={{
|
||||
item: { padding: 0 },
|
||||
@ -284,6 +208,11 @@ const Tickets = (obj) => {
|
||||
content: { padding: 0, paddingTop: '1em', paddingBottom: '1em' },
|
||||
contentInner: { padding: 0 },
|
||||
}}>
|
||||
<Accordion.Item
|
||||
label={"Current Stake Overview"}
|
||||
className="stroke">
|
||||
<StakeOverview />
|
||||
</Accordion.Item>
|
||||
{
|
||||
ticketsPerMonth.map(function (data) {
|
||||
let thisMonth = "";
|
||||
|
Loading…
x
Reference in New Issue
Block a user