mirror of
https://github.com/stronk-dev/LivepeerEvents.git
synced 2025-07-05 10:45:10 +02:00
Moore pages
This commit is contained in:
parent
ff2fc48dc8
commit
bbcace68cf
162
src/components/MonthlyFactoids.js
Normal file
162
src/components/MonthlyFactoids.js
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Ticket from "../components/TicketViewer";
|
||||||
|
import ScrollContainer from 'react-indiana-drag-scroll';
|
||||||
|
|
||||||
|
const claimColour = "rgba(25, 158, 29, 0.4)";
|
||||||
|
const stakeColour = "rgba(25, 158, 147, 0.4)";
|
||||||
|
const ticketRedeemColour = "rgba(25, 98, 158, 0.4)";
|
||||||
|
const rewardColour = "rgba(25, 27, 158, 0.4)";
|
||||||
|
const unbondColour = "rgba(105, 25, 158, 0.4)";
|
||||||
|
const updateColour = "rgba(158, 25, 52, 0.4)";
|
||||||
|
const withdrawStakeColour = "rgba(158, 98, 25, 0.4)";
|
||||||
|
const activationColour = "rgba(154, 158, 25, 0.4)";
|
||||||
|
const ticketTransferColour = "rgba(88, 91, 42, 0.3)";
|
||||||
|
const greyColour = "rgba(122, 128, 127, 0.4)";
|
||||||
|
|
||||||
|
const MonthlyFactoids = (obj) => {
|
||||||
|
// Pies for stake overview, if have stake data for that month saved
|
||||||
|
let totalStakeSum = 0;
|
||||||
|
if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) {
|
||||||
|
let ticketIdx = obj.data.latestTotalStake.length - 1;
|
||||||
|
// Calc total stake at that time
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
totalStakeSum += thisTicket.totalStake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="stroke insetEffect" key={obj.seed + "factoids"} style={{ height: '70vh' }}>
|
||||||
|
<div className="content-wrapper">
|
||||||
|
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}>
|
||||||
|
<div className="overflow-content" style={{ cursor: 'grab', maxHeight: '70vh' }}>
|
||||||
|
{obj.data.reactivationCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: activationColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-reactivationCount-"} icon={"🔌"} subtext={obj.data.reactivationCount + " reactivations"} descriptions={[
|
||||||
|
obj.data.reactivationCount + " Orchestrators reactivated"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
|
||||||
|
{obj.data.activationCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: activationColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔧"} subtext={obj.data.activationCount + " new orchestrators"} descriptions={[
|
||||||
|
obj.data.activationCount + " orchestrators joined with an initial stake of " + obj.data.activationInitialSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{(obj.data.latestCommission && obj.data.latestCommission.length) ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: updateColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔗"} subtext={obj.data.latestCommission.length + " orchestrators found"} descriptions={[
|
||||||
|
obj.data.latestCommission.length + " orchestrators had a total of " + totalStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT staked to them"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null}
|
||||||
|
{obj.data.bondCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: stakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"📈"} subtext={obj.data.bondCount + " new delegators"} descriptions={[
|
||||||
|
obj.data.bondCount + " accounts delegated for the first time for a total of " + obj.data.bondStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.unbondCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: unbondColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"📉"} subtext={obj.data.unbondCount + " leaving delegators"} descriptions={[
|
||||||
|
obj.data.unbondCount + " delegators unbonded " + obj.data.unbondStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.rewardCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: rewardColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"⌛"} subtext={obj.data.rewardCount + " reward calls"} descriptions={[
|
||||||
|
obj.data.rewardCount + " reward calls made by orchestrators were worth " + obj.data.rewardAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.claimCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: claimColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🏦"} subtext={obj.data.claimCount + " reward claims"} descriptions={[
|
||||||
|
obj.data.claimRewardSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT and " + obj.data.claimFeeSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH worth of rewards were claimed by delegators"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.withdrawStakeCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: withdrawStakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"💸"} subtext={obj.data.withdrawStakeCount + " withdraw reward calls"} descriptions={[
|
||||||
|
obj.data.withdrawStakeAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT worth of staking rewards were withdrawn to the account of the delegator"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.withdrawFeesCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: withdrawStakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"💸"} subtext={obj.data.withdrawFeesCount + " withdraw fee calls"} descriptions={[
|
||||||
|
obj.data.withdrawFeesAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH worth of transcoding fees were withdrawn to the account of the delegator"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.moveStakeCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: stakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔄"} subtext={obj.data.moveStakeCount + " stake movements"} descriptions={[
|
||||||
|
obj.data.moveStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT worth of stake was moved between orchestrators"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.winningTicketsReceivedCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: ticketTransferColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🎫"} subtext={obj.data.winningTicketsReceivedCount + " winning tickets"} descriptions={[
|
||||||
|
obj.data.winningTicketsReceivedCount + " winning tickets were sent out by " + obj.data.winningTicketsSent.length + " broadcasters"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
{obj.data.winningTicketsRedeemedCount ?
|
||||||
|
<div className="stroke">
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: ticketRedeemColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
||||||
|
<Ticket seed={obj.seed + "-neworchs-"} icon={"🎟️"} subtext={obj.data.winningTicketsRedeemedCount + " redeemed tickets"} descriptions={[
|
||||||
|
obj.data.winningTicketsRedeemedCount + " winning tickets were redeemed worth " + obj.data.winningTicketsRedeemedSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH"
|
||||||
|
]} />
|
||||||
|
</div>
|
||||||
|
</div> : null
|
||||||
|
}
|
||||||
|
<div className="halfVerticalDivider" />
|
||||||
|
</div>
|
||||||
|
</ScrollContainer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MonthlyFactoids;
|
419
src/components/MonthlyGraphs.js
Normal file
419
src/components/MonthlyGraphs.js
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import { VictoryPie } from 'victory';
|
||||||
|
import { Pagination } from "@mantine/core";
|
||||||
|
|
||||||
|
const MonthlyGraphs = (obj) => {
|
||||||
|
const livepeer = useSelector((state) => state.livepeerstate);
|
||||||
|
const [activeGraph, setGraph] = useState(1);
|
||||||
|
|
||||||
|
let totalGraphs = 0;
|
||||||
|
|
||||||
|
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) + "..");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show all orchs (if latestTotalStake exists) or show only those in winningTicketsReceived
|
||||||
|
let orchList;
|
||||||
|
let ticketList = obj.data.winningTicketsReceived || [];
|
||||||
|
let stakeList = obj.data.latestTotalStake || [];
|
||||||
|
|
||||||
|
// Pies for stake overview, if have stake data for that month saved
|
||||||
|
let stakeObj;
|
||||||
|
let totalStakeSum = 0;
|
||||||
|
if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) {
|
||||||
|
orchList = [...obj.data.latestTotalStake];
|
||||||
|
let pieList = [];
|
||||||
|
let otherSum = 0;
|
||||||
|
let ticketIdx = obj.data.latestTotalStake.length - 1;
|
||||||
|
// Calc total stake at that time
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
totalStakeSum += thisTicket.totalStake;
|
||||||
|
}
|
||||||
|
ticketIdx = obj.data.latestTotalStake.length - 1;
|
||||||
|
// Create pie chart
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
if ((thisTicket.totalStake / totalStakeSum) < 0.015) {
|
||||||
|
otherSum += thisTicket.totalStake;
|
||||||
|
} else {
|
||||||
|
pieList.push({
|
||||||
|
address: getName(thisTicket.address),
|
||||||
|
sum: thisTicket.totalStake
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((otherSum / totalStakeSum) > 0.01) {
|
||||||
|
pieList.push({
|
||||||
|
address: "Other",
|
||||||
|
sum: otherSum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
totalGraphs++;
|
||||||
|
|
||||||
|
stakeObj = <div className="stroke">
|
||||||
|
<h4>Stake Distribution</h4>
|
||||||
|
<VictoryPie padding={0} data={pieList} x="address" y="sum"
|
||||||
|
sortOrder="descending"
|
||||||
|
sortKey="sum"
|
||||||
|
radius={300}
|
||||||
|
width={620}
|
||||||
|
height={620}
|
||||||
|
innerRadius={50}
|
||||||
|
labelRadius={130}
|
||||||
|
cornerRadius={3}
|
||||||
|
colorScale={[
|
||||||
|
"#282678",
|
||||||
|
"#56256c",
|
||||||
|
"#872974",
|
||||||
|
"#b63074",
|
||||||
|
"#de416d",
|
||||||
|
"#ff5c5f",
|
||||||
|
"#ffe085",
|
||||||
|
"#f0e575",
|
||||||
|
"#daec69",
|
||||||
|
"#bef262",
|
||||||
|
"#97f964",
|
||||||
|
"#5cff6f",
|
||||||
|
"#14ff47",
|
||||||
|
"#00fb94",
|
||||||
|
"#00f3cd",
|
||||||
|
"#00e7f3",
|
||||||
|
"#00d8ff",
|
||||||
|
"#24c8ff",
|
||||||
|
"#0a78ff",
|
||||||
|
"#5864d7",
|
||||||
|
"#6952b1",
|
||||||
|
"#69448d",
|
||||||
|
"#61386c",
|
||||||
|
"#522f50"
|
||||||
|
]}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
||||||
|
data: {
|
||||||
|
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
fontSize: 16, zIndex: 999
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
labelPosition="centroid"
|
||||||
|
labelPlacement="parallel"
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
} else {
|
||||||
|
orchList = [...obj.data.winningTicketsReceived];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pies for earnings overview
|
||||||
|
let earningsObj;
|
||||||
|
if (obj.data.winningTicketsReceived && obj.data.winningTicketsReceived.length) {
|
||||||
|
let otherSum = 0;
|
||||||
|
let pieList = [];
|
||||||
|
let ticketIdx = obj.data.winningTicketsReceived.length - 1;
|
||||||
|
// Create pie chart
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.winningTicketsReceived[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
if ((thisTicket.sum / obj.data.winningTicketsReceivedSum) < 0.015) {
|
||||||
|
otherSum += thisTicket.sum;
|
||||||
|
} else {
|
||||||
|
pieList.push({
|
||||||
|
address: getName(thisTicket.address),
|
||||||
|
sum: thisTicket.sum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((otherSum / obj.data.winningTicketsReceivedSum) > 0.01) {
|
||||||
|
pieList.push({
|
||||||
|
address: "Other",
|
||||||
|
sum: otherSum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
totalGraphs++;
|
||||||
|
|
||||||
|
earningsObj = <div className="stroke">
|
||||||
|
<h4>Earnings Distribution</h4>
|
||||||
|
<VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
|
||||||
|
sortOrder="descending"
|
||||||
|
sortKey="sum"
|
||||||
|
radius={300}
|
||||||
|
width={620}
|
||||||
|
height={620}
|
||||||
|
innerRadius={50}
|
||||||
|
labelRadius={130}
|
||||||
|
cornerRadius={3}
|
||||||
|
colorScale={[
|
||||||
|
"#282678",
|
||||||
|
"#56256c",
|
||||||
|
"#872974",
|
||||||
|
"#b63074",
|
||||||
|
"#de416d",
|
||||||
|
"#ff5c5f",
|
||||||
|
"#ffe085",
|
||||||
|
"#f0e575",
|
||||||
|
"#daec69",
|
||||||
|
"#bef262",
|
||||||
|
"#97f964",
|
||||||
|
"#5cff6f",
|
||||||
|
"#14ff47",
|
||||||
|
"#00fb94",
|
||||||
|
"#00f3cd",
|
||||||
|
"#00e7f3",
|
||||||
|
"#00d8ff",
|
||||||
|
"#24c8ff",
|
||||||
|
"#0a78ff",
|
||||||
|
"#5864d7",
|
||||||
|
"#6952b1",
|
||||||
|
"#69448d",
|
||||||
|
"#61386c",
|
||||||
|
"#522f50"
|
||||||
|
]}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
||||||
|
data: {
|
||||||
|
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
fontSize: 16, zIndex: 999
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
labelPosition="centroid"
|
||||||
|
labelPlacement="parallel"
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pies for broadcaster payout
|
||||||
|
let broadcasterObj;
|
||||||
|
if (obj.data.winningTicketsSent && obj.data.winningTicketsSent.length) {
|
||||||
|
let otherSum = 0;
|
||||||
|
let pieList = [];
|
||||||
|
let ticketIdx = obj.data.winningTicketsSent.length - 1;
|
||||||
|
// Create pie chart
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.winningTicketsSent[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
if ((thisTicket.sum / obj.data.winningTicketsReceivedSum) < 0.015) {
|
||||||
|
otherSum += thisTicket.sum;
|
||||||
|
} else {
|
||||||
|
pieList.push({
|
||||||
|
address: getName(thisTicket.address),
|
||||||
|
sum: thisTicket.sum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((otherSum / obj.data.winningTicketsReceivedSum) > 0.01) {
|
||||||
|
pieList.push({
|
||||||
|
address: "Other",
|
||||||
|
sum: otherSum
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("+1 for tickets");
|
||||||
|
console.log(obj.data.winningTicketsSent);
|
||||||
|
console.log(obj.data.winningTicketsReceivedSum);
|
||||||
|
console.log(pieList);
|
||||||
|
|
||||||
|
totalGraphs++;
|
||||||
|
|
||||||
|
broadcasterObj = <div className="stroke">
|
||||||
|
<h4>Broadcaster Payments</h4>
|
||||||
|
<VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
|
||||||
|
sortOrder="descending"
|
||||||
|
sortKey="sum"
|
||||||
|
radius={300}
|
||||||
|
width={620}
|
||||||
|
height={620}
|
||||||
|
innerRadius={50}
|
||||||
|
labelRadius={130}
|
||||||
|
cornerRadius={3}
|
||||||
|
colorScale={[
|
||||||
|
"#282678",
|
||||||
|
"#56256c",
|
||||||
|
"#872974",
|
||||||
|
"#b63074",
|
||||||
|
"#de416d",
|
||||||
|
"#ff5c5f",
|
||||||
|
"#ffe085",
|
||||||
|
"#f0e575",
|
||||||
|
"#daec69",
|
||||||
|
"#bef262",
|
||||||
|
"#97f964",
|
||||||
|
"#5cff6f",
|
||||||
|
"#14ff47",
|
||||||
|
"#00fb94",
|
||||||
|
"#00f3cd",
|
||||||
|
"#00e7f3",
|
||||||
|
"#00d8ff",
|
||||||
|
"#24c8ff",
|
||||||
|
"#0a78ff",
|
||||||
|
"#5864d7",
|
||||||
|
"#6952b1",
|
||||||
|
"#69448d",
|
||||||
|
"#61386c",
|
||||||
|
"#522f50"
|
||||||
|
]}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
||||||
|
data: {
|
||||||
|
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
fontSize: 16, zIndex: 999
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
labelPosition="centroid"
|
||||||
|
labelPlacement="parallel"
|
||||||
|
/>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let sortedList = [];
|
||||||
|
if (orchList.length) {
|
||||||
|
// Sort this months data
|
||||||
|
while (orchList.length) {
|
||||||
|
let ticketIdx2 = orchList.length - 1;
|
||||||
|
let largestIdx = 0;
|
||||||
|
let largestValue = 0;
|
||||||
|
|
||||||
|
// Find current O with most ticket wins in Eth
|
||||||
|
while (ticketIdx2 >= 0) {
|
||||||
|
const currentOrch = orchList[ticketIdx2];
|
||||||
|
let thisVal;
|
||||||
|
|
||||||
|
for (const obj of ticketList) {
|
||||||
|
if (obj.address == currentOrch.address) {
|
||||||
|
thisVal = obj.sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisVal) {
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (thisVal > largestValue) {
|
||||||
|
largestIdx = ticketIdx2;
|
||||||
|
largestValue = thisVal;
|
||||||
|
}
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
}
|
||||||
|
// Else try to sort by stake
|
||||||
|
if (!largestValue) {
|
||||||
|
ticketIdx2 = orchList.length - 1;
|
||||||
|
while (ticketIdx2 >= 0) {
|
||||||
|
const currentOrch = orchList[ticketIdx2];
|
||||||
|
let thisVal;
|
||||||
|
|
||||||
|
for (const obj of stakeList) {
|
||||||
|
if (obj.address == currentOrch.address) {
|
||||||
|
thisVal = obj.totalStake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisVal) {
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (thisVal > largestValue) {
|
||||||
|
largestIdx = ticketIdx2;
|
||||||
|
largestValue = thisVal;
|
||||||
|
}
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Push current biggest list
|
||||||
|
sortedList.push(orchList[largestIdx]);
|
||||||
|
// Remove from list
|
||||||
|
orchList.splice(largestIdx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let renderStake = false;
|
||||||
|
let renderEarnings = false;
|
||||||
|
let renderBread = false;
|
||||||
|
let graphIndex = activeGraph;
|
||||||
|
if (totalGraphs && stakeObj) {
|
||||||
|
if (graphIndex == 1) {
|
||||||
|
renderStake = true;
|
||||||
|
graphIndex = 0;
|
||||||
|
} else {
|
||||||
|
graphIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (graphIndex == 1 && graphIndex && totalGraphs && earningsObj) {
|
||||||
|
if (graphIndex == 1) {
|
||||||
|
renderEarnings = true;
|
||||||
|
graphIndex = 0;
|
||||||
|
} else {
|
||||||
|
graphIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphIndex--;
|
||||||
|
if (graphIndex == 1 && graphIndex && totalGraphs && broadcasterObj) {
|
||||||
|
if (graphIndex == 1) {
|
||||||
|
renderBread = true;
|
||||||
|
graphIndex = 0;
|
||||||
|
} else {
|
||||||
|
graphIndex--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="stroke insetEffect" key={obj.seed + "graphs"} style={{ height: '70vh' }}>
|
||||||
|
{renderStake ? stakeObj : null}
|
||||||
|
{renderEarnings ? earningsObj : null}
|
||||||
|
{renderBread ? broadcasterObj : null}
|
||||||
|
<div className="row" style={{ marginTop: '1em', marginBottom: '1em' }}>
|
||||||
|
{totalGraphs > 1 ?
|
||||||
|
<Pagination page={activeGraph} onChange={setGraph} total={totalGraphs} siblings={1} initialPage={1} />
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MonthlyGraphs;
|
179
src/components/MonthlyOrchestrators.js
Normal file
179
src/components/MonthlyOrchestrators.js
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
|
import ScrollContainer from "react-indiana-drag-scroll";
|
||||||
|
import Winner from '../components/WinnerStat';
|
||||||
|
import {
|
||||||
|
getOrchestratorScores
|
||||||
|
} from "../actions/livepeer";
|
||||||
|
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);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const setScore = async () => {
|
||||||
|
if (!obj.data.testScores) {
|
||||||
|
const freshScore = await getOrchestratorScores(obj.data.year, obj.data.month);
|
||||||
|
if (freshScore) {
|
||||||
|
setThisScores(freshScore);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setThisScores(obj.data.testScores);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setScore();
|
||||||
|
}, [obj.data.testScores]);
|
||||||
|
|
||||||
|
// Show all orchs (if latestTotalStake exists) or show only those in winningTicketsReceived
|
||||||
|
let orchList;
|
||||||
|
let ticketList = obj.data.winningTicketsReceived || [];
|
||||||
|
let commissionList = obj.data.latestCommission || [];
|
||||||
|
let stakeList = obj.data.latestTotalStake || [];
|
||||||
|
|
||||||
|
// Pies for stake overview, if have stake data for that month saved
|
||||||
|
let totalStakeSum = 0;
|
||||||
|
if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) {
|
||||||
|
orchList = [...obj.data.latestTotalStake];
|
||||||
|
let ticketIdx = obj.data.latestTotalStake.length - 1;
|
||||||
|
// Calc total stake at that time
|
||||||
|
while (ticketIdx >= 0) {
|
||||||
|
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
||||||
|
ticketIdx -= 1;
|
||||||
|
totalStakeSum += thisTicket.totalStake;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
orchList = [...obj.data.winningTicketsReceived];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let sortedList = [];
|
||||||
|
if (orchList.length) {
|
||||||
|
// Sort this months data
|
||||||
|
while (orchList.length) {
|
||||||
|
let ticketIdx2 = orchList.length - 1;
|
||||||
|
let largestIdx = 0;
|
||||||
|
let largestValue = 0;
|
||||||
|
|
||||||
|
// Find current O with most ticket wins in Eth
|
||||||
|
while (ticketIdx2 >= 0) {
|
||||||
|
const currentOrch = orchList[ticketIdx2];
|
||||||
|
let thisVal;
|
||||||
|
|
||||||
|
for (const obj of ticketList) {
|
||||||
|
if (obj.address == currentOrch.address) {
|
||||||
|
thisVal = obj.sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisVal) {
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (thisVal > largestValue) {
|
||||||
|
largestIdx = ticketIdx2;
|
||||||
|
largestValue = thisVal;
|
||||||
|
}
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
}
|
||||||
|
// Else try to sort by stake
|
||||||
|
if (!largestValue) {
|
||||||
|
ticketIdx2 = orchList.length - 1;
|
||||||
|
while (ticketIdx2 >= 0) {
|
||||||
|
const currentOrch = orchList[ticketIdx2];
|
||||||
|
let thisVal;
|
||||||
|
|
||||||
|
for (const obj of stakeList) {
|
||||||
|
if (obj.address == currentOrch.address) {
|
||||||
|
thisVal = obj.totalStake;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thisVal) {
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (thisVal > largestValue) {
|
||||||
|
largestIdx = ticketIdx2;
|
||||||
|
largestValue = thisVal;
|
||||||
|
}
|
||||||
|
ticketIdx2 -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Push current biggest list
|
||||||
|
sortedList.push(orchList[largestIdx]);
|
||||||
|
// Remove from list
|
||||||
|
orchList.splice(largestIdx, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const totalPages = (sortedList.length + (itemsPerPage - (sortedList.length % itemsPerPage))) / itemsPerPage;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="stroke fullMargin insetEffect" style={{ padding: 0, margin: 0, height: '70vh' }}>
|
||||||
|
<div className="content-wrapper">
|
||||||
|
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}>
|
||||||
|
<div className="overflow-content" style={{ cursor: 'grab', maxHeight: '300px' }}>
|
||||||
|
{
|
||||||
|
sortedList.map(function (orch, i) {
|
||||||
|
const tmp = i - ((activePage - 1) * itemsPerPage);
|
||||||
|
if (tmp >= 0 && tmp < itemsPerPage) {
|
||||||
|
let thisCommission = null;
|
||||||
|
let thisStake = null;
|
||||||
|
let thisEarnings = null;
|
||||||
|
|
||||||
|
for (const obj of ticketList) {
|
||||||
|
if (obj.address == orch.address) {
|
||||||
|
thisEarnings = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const obj of commissionList) {
|
||||||
|
if (obj.address == orch.address) {
|
||||||
|
thisCommission = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const obj of stakeList) {
|
||||||
|
if (obj.address == orch.address) {
|
||||||
|
thisStake = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let thisScore = null;
|
||||||
|
if (thisScores && thisScores.scores) {
|
||||||
|
thisScore = thisScores.scores[orch.address];
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className='stroke' key={obj.seed + orch.address + i}>
|
||||||
|
<Winner
|
||||||
|
thisScore={thisScore}
|
||||||
|
totalEarnings={obj.data.winningTicketsReceivedSum}
|
||||||
|
thisEarnings={thisEarnings}
|
||||||
|
totalStake={totalStakeSum}
|
||||||
|
thisStake={thisStake}
|
||||||
|
thisCommission={thisCommission}
|
||||||
|
address={orch.address}
|
||||||
|
thisIndex={i + 1}
|
||||||
|
seed={obj.seed + "win" + orch.address + i}
|
||||||
|
/>
|
||||||
|
<div className="verticalDivider" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</ScrollContainer>
|
||||||
|
</div>
|
||||||
|
<div className="row" style={{ marginTop: '1em', marginBottom: '1em' }}>
|
||||||
|
{totalPages > 1 ?
|
||||||
|
<Pagination page={activePage} onChange={setPage} total={totalPages} siblings={1} initialPage={1} />
|
||||||
|
: null}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MonthlyOrchestrators;
|
@ -94,7 +94,7 @@ const Address = (obj) => {
|
|||||||
}
|
}
|
||||||
if (thisInfo.image) {
|
if (thisInfo.image) {
|
||||||
thisIcon =
|
thisIcon =
|
||||||
<a className="selectOrch" style={{ marginRight: '0.5em', cursor: 'grab'}} disabled>
|
<a className="selectOrch" style={{ marginRight: '0.5em', cursor: 'grab' }} disabled>
|
||||||
<img alt="" src={"https://cloudflare-ipfs.com/ipfs/" + thisInfo.image} width="20em" height="20em" style={{ margin: 0, padding: 0 }} />
|
<img alt="" src={"https://cloudflare-ipfs.com/ipfs/" + thisInfo.image} width="20em" height="20em" style={{ margin: 0, padding: 0 }} />
|
||||||
</a >
|
</a >
|
||||||
} else {
|
} else {
|
||||||
@ -111,7 +111,7 @@ const Address = (obj) => {
|
|||||||
<img alt="" src="livepeer.png" width="20em" height="20em" />
|
<img alt="" src="livepeer.png" width="20em" height="20em" />
|
||||||
</a>
|
</a>
|
||||||
{thisIcon}
|
{thisIcon}
|
||||||
<span className="elipsText elipsOnMobileExtra">{thisName}</span>
|
<span className="elipsText elipsOnMobileExtra" style={{ width: '100%' }}>{thisName}</span>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,623 +0,0 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
|
||||||
import { useSelector } from 'react-redux';
|
|
||||||
import { VictoryPie } from 'victory';
|
|
||||||
import ScrollContainer from "react-indiana-drag-scroll";
|
|
||||||
import Winner from '../components/WinnerStat';
|
|
||||||
import {
|
|
||||||
getOrchestratorScores
|
|
||||||
} from "../actions/livepeer";
|
|
||||||
import Ticket from "../components/TicketViewer";
|
|
||||||
import { Pagination } from "@mantine/core";
|
|
||||||
|
|
||||||
const claimColour = "rgba(25, 158, 29, 0.4)";
|
|
||||||
const stakeColour = "rgba(25, 158, 147, 0.4)";
|
|
||||||
const ticketRedeemColour = "rgba(25, 98, 158, 0.4)";
|
|
||||||
const rewardColour = "rgba(25, 27, 158, 0.4)";
|
|
||||||
const unbondColour = "rgba(105, 25, 158, 0.4)";
|
|
||||||
const updateColour = "rgba(158, 25, 52, 0.4)";
|
|
||||||
const withdrawStakeColour = "rgba(158, 98, 25, 0.4)";
|
|
||||||
const activationColour = "rgba(154, 158, 25, 0.4)";
|
|
||||||
const ticketTransferColour = "rgba(88, 91, 42, 0.3)";
|
|
||||||
const greyColour = "rgba(122, 128, 127, 0.4)";
|
|
||||||
|
|
||||||
const itemsPerPage = 10;
|
|
||||||
|
|
||||||
const WinnerMonth = (obj) => {
|
|
||||||
const livepeer = useSelector((state) => state.livepeerstate);
|
|
||||||
const [thisScores, setThisScores] = useState(null);
|
|
||||||
const [activePage, setPage] = useState(1);
|
|
||||||
const [activeGraph, setGraph] = useState(1);
|
|
||||||
|
|
||||||
let totalGraphs = 0;
|
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
const setScore = async () => {
|
|
||||||
if (!obj.data.testScores) {
|
|
||||||
const freshScore = await getOrchestratorScores(obj.data.year, obj.data.month);
|
|
||||||
if (freshScore) {
|
|
||||||
setThisScores(freshScore);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setThisScores(obj.data.testScores);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setScore();
|
|
||||||
}, [obj.data.testScores]);
|
|
||||||
|
|
||||||
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) + "..");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show all orchs (if latestTotalStake exists) or show only those in winningTicketsReceived
|
|
||||||
let orchList;
|
|
||||||
let ticketList = obj.data.winningTicketsReceived || [];
|
|
||||||
let commissionList = obj.data.latestCommission || [];
|
|
||||||
let stakeList = obj.data.latestTotalStake || [];
|
|
||||||
|
|
||||||
// Pies for stake overview, if have stake data for that month saved
|
|
||||||
let stakeObj;
|
|
||||||
let totalStakeSum = 0;
|
|
||||||
if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) {
|
|
||||||
orchList = [...obj.data.latestTotalStake];
|
|
||||||
let pieList = [];
|
|
||||||
let otherSum = 0;
|
|
||||||
let ticketIdx = obj.data.latestTotalStake.length - 1;
|
|
||||||
// Calc total stake at that time
|
|
||||||
while (ticketIdx >= 0) {
|
|
||||||
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
|
||||||
ticketIdx -= 1;
|
|
||||||
totalStakeSum += thisTicket.totalStake;
|
|
||||||
}
|
|
||||||
ticketIdx = obj.data.latestTotalStake.length - 1;
|
|
||||||
// Create pie chart
|
|
||||||
while (ticketIdx >= 0) {
|
|
||||||
const thisTicket = obj.data.latestTotalStake[ticketIdx];
|
|
||||||
ticketIdx -= 1;
|
|
||||||
if ((thisTicket.totalStake / totalStakeSum) < 0.015) {
|
|
||||||
otherSum += thisTicket.totalStake;
|
|
||||||
} else {
|
|
||||||
pieList.push({
|
|
||||||
address: getName(thisTicket.address),
|
|
||||||
sum: thisTicket.totalStake
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((otherSum / totalStakeSum) > 0.01) {
|
|
||||||
pieList.push({
|
|
||||||
address: "Other",
|
|
||||||
sum: otherSum
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
totalGraphs++;
|
|
||||||
|
|
||||||
stakeObj = <div className="stroke">
|
|
||||||
<h4>Stake Distribution</h4>
|
|
||||||
<VictoryPie padding={0} data={pieList} x="address" y="sum"
|
|
||||||
sortOrder="descending"
|
|
||||||
sortKey="sum"
|
|
||||||
radius={300}
|
|
||||||
width={620}
|
|
||||||
height={620}
|
|
||||||
innerRadius={50}
|
|
||||||
labelRadius={130}
|
|
||||||
cornerRadius={3}
|
|
||||||
colorScale={[
|
|
||||||
"#282678",
|
|
||||||
"#56256c",
|
|
||||||
"#872974",
|
|
||||||
"#b63074",
|
|
||||||
"#de416d",
|
|
||||||
"#ff5c5f",
|
|
||||||
"#ffe085",
|
|
||||||
"#f0e575",
|
|
||||||
"#daec69",
|
|
||||||
"#bef262",
|
|
||||||
"#97f964",
|
|
||||||
"#5cff6f",
|
|
||||||
"#14ff47",
|
|
||||||
"#00fb94",
|
|
||||||
"#00f3cd",
|
|
||||||
"#00e7f3",
|
|
||||||
"#00d8ff",
|
|
||||||
"#24c8ff",
|
|
||||||
"#0a78ff",
|
|
||||||
"#5864d7",
|
|
||||||
"#6952b1",
|
|
||||||
"#69448d",
|
|
||||||
"#61386c",
|
|
||||||
"#522f50"
|
|
||||||
]}
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
|
||||||
data: {
|
|
||||||
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
fontSize: 16, zIndex: 999
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
labelPosition="centroid"
|
|
||||||
labelPlacement="parallel"
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
} else {
|
|
||||||
orchList = [...obj.data.winningTicketsReceived];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pies for earnings overview
|
|
||||||
let earningsObj;
|
|
||||||
if (obj.data.winningTicketsReceived && obj.data.winningTicketsReceived.length) {
|
|
||||||
let otherSum = 0;
|
|
||||||
let pieList = [];
|
|
||||||
let ticketIdx = obj.data.winningTicketsReceived.length - 1;
|
|
||||||
// Create pie chart
|
|
||||||
while (ticketIdx >= 0) {
|
|
||||||
const thisTicket = obj.data.winningTicketsReceived[ticketIdx];
|
|
||||||
ticketIdx -= 1;
|
|
||||||
if ((thisTicket.sum / obj.data.winningTicketsReceivedSum) < 0.015) {
|
|
||||||
otherSum += thisTicket.sum;
|
|
||||||
} else {
|
|
||||||
pieList.push({
|
|
||||||
address: getName(thisTicket.address),
|
|
||||||
sum: thisTicket.sum
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((otherSum / obj.data.winningTicketsReceivedSum) > 0.01) {
|
|
||||||
pieList.push({
|
|
||||||
address: "Other",
|
|
||||||
sum: otherSum
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
totalGraphs++;
|
|
||||||
|
|
||||||
earningsObj = <div className="stroke">
|
|
||||||
<h4>Earnings Distribution</h4>
|
|
||||||
<VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
|
|
||||||
sortOrder="descending"
|
|
||||||
sortKey="sum"
|
|
||||||
radius={300}
|
|
||||||
width={620}
|
|
||||||
height={620}
|
|
||||||
innerRadius={50}
|
|
||||||
labelRadius={130}
|
|
||||||
cornerRadius={3}
|
|
||||||
colorScale={[
|
|
||||||
"#282678",
|
|
||||||
"#56256c",
|
|
||||||
"#872974",
|
|
||||||
"#b63074",
|
|
||||||
"#de416d",
|
|
||||||
"#ff5c5f",
|
|
||||||
"#ffe085",
|
|
||||||
"#f0e575",
|
|
||||||
"#daec69",
|
|
||||||
"#bef262",
|
|
||||||
"#97f964",
|
|
||||||
"#5cff6f",
|
|
||||||
"#14ff47",
|
|
||||||
"#00fb94",
|
|
||||||
"#00f3cd",
|
|
||||||
"#00e7f3",
|
|
||||||
"#00d8ff",
|
|
||||||
"#24c8ff",
|
|
||||||
"#0a78ff",
|
|
||||||
"#5864d7",
|
|
||||||
"#6952b1",
|
|
||||||
"#69448d",
|
|
||||||
"#61386c",
|
|
||||||
"#522f50"
|
|
||||||
]}
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
|
||||||
data: {
|
|
||||||
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
fontSize: 16, zIndex: 999
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
labelPosition="centroid"
|
|
||||||
labelPlacement="parallel"
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pies for broadcaster payout
|
|
||||||
let broadcasterObj;
|
|
||||||
if (obj.data.winningTicketsSent && obj.data.winningTicketsSent.length) {
|
|
||||||
let otherSum = 0;
|
|
||||||
let pieList = [];
|
|
||||||
let ticketIdx = obj.data.winningTicketsSent.length - 1;
|
|
||||||
// Create pie chart
|
|
||||||
while (ticketIdx >= 0) {
|
|
||||||
const thisTicket = obj.data.winningTicketsSent[ticketIdx];
|
|
||||||
ticketIdx -= 1;
|
|
||||||
if ((thisTicket.sum / obj.data.winningTicketsReceivedSum) < 0.015) {
|
|
||||||
otherSum += thisTicket.sum;
|
|
||||||
} else {
|
|
||||||
pieList.push({
|
|
||||||
address: getName(thisTicket.address),
|
|
||||||
sum: thisTicket.sum
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((otherSum / obj.data.winningTicketsReceivedSum) > 0.01) {
|
|
||||||
pieList.push({
|
|
||||||
address: "Other",
|
|
||||||
sum: otherSum
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
totalGraphs++;
|
|
||||||
|
|
||||||
broadcasterObj = <div className="stroke">
|
|
||||||
<h4>Broadcaster Payments</h4>
|
|
||||||
<VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
|
|
||||||
sortOrder="descending"
|
|
||||||
sortKey="sum"
|
|
||||||
radius={300}
|
|
||||||
width={620}
|
|
||||||
height={620}
|
|
||||||
innerRadius={50}
|
|
||||||
labelRadius={130}
|
|
||||||
cornerRadius={3}
|
|
||||||
colorScale={[
|
|
||||||
"#282678",
|
|
||||||
"#56256c",
|
|
||||||
"#872974",
|
|
||||||
"#b63074",
|
|
||||||
"#de416d",
|
|
||||||
"#ff5c5f",
|
|
||||||
"#ffe085",
|
|
||||||
"#f0e575",
|
|
||||||
"#daec69",
|
|
||||||
"#bef262",
|
|
||||||
"#97f964",
|
|
||||||
"#5cff6f",
|
|
||||||
"#14ff47",
|
|
||||||
"#00fb94",
|
|
||||||
"#00f3cd",
|
|
||||||
"#00e7f3",
|
|
||||||
"#00d8ff",
|
|
||||||
"#24c8ff",
|
|
||||||
"#0a78ff",
|
|
||||||
"#5864d7",
|
|
||||||
"#6952b1",
|
|
||||||
"#69448d",
|
|
||||||
"#61386c",
|
|
||||||
"#522f50"
|
|
||||||
]}
|
|
||||||
style={{
|
|
||||||
backgroundColor: 'rgba(122, 128, 127, 0.4)',
|
|
||||||
data: {
|
|
||||||
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 1.5
|
|
||||||
},
|
|
||||||
labels: {
|
|
||||||
fontSize: 16, zIndex: 999
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
labelPosition="centroid"
|
|
||||||
labelPlacement="parallel"
|
|
||||||
/>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sortedList = [];
|
|
||||||
if (orchList.length) {
|
|
||||||
// Sort this months data
|
|
||||||
while (orchList.length) {
|
|
||||||
let ticketIdx2 = orchList.length - 1;
|
|
||||||
let largestIdx = 0;
|
|
||||||
let largestValue = 0;
|
|
||||||
|
|
||||||
// Find current O with most ticket wins in Eth
|
|
||||||
while (ticketIdx2 >= 0) {
|
|
||||||
const currentOrch = orchList[ticketIdx2];
|
|
||||||
let thisVal;
|
|
||||||
|
|
||||||
for (const obj of ticketList) {
|
|
||||||
if (obj.address == currentOrch.address) {
|
|
||||||
thisVal = obj.sum;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!thisVal) {
|
|
||||||
ticketIdx2 -= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (thisVal > largestValue) {
|
|
||||||
largestIdx = ticketIdx2;
|
|
||||||
largestValue = thisVal;
|
|
||||||
}
|
|
||||||
ticketIdx2 -= 1;
|
|
||||||
}
|
|
||||||
// Else try to sort by stake
|
|
||||||
if (!largestValue) {
|
|
||||||
ticketIdx2 = orchList.length - 1;
|
|
||||||
while (ticketIdx2 >= 0) {
|
|
||||||
const currentOrch = orchList[ticketIdx2];
|
|
||||||
let thisVal;
|
|
||||||
|
|
||||||
for (const obj of stakeList) {
|
|
||||||
if (obj.address == currentOrch.address) {
|
|
||||||
thisVal = obj.totalStake;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!thisVal) {
|
|
||||||
ticketIdx2 -= 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (thisVal > largestValue) {
|
|
||||||
largestIdx = ticketIdx2;
|
|
||||||
largestValue = thisVal;
|
|
||||||
}
|
|
||||||
ticketIdx2 -= 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Push current biggest list
|
|
||||||
sortedList.push(orchList[largestIdx]);
|
|
||||||
// Remove from list
|
|
||||||
orchList.splice(largestIdx, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalPages = (sortedList.length + (itemsPerPage - (sortedList.length % itemsPerPage))) / itemsPerPage;
|
|
||||||
let renderStake = false;
|
|
||||||
let renderEarnings = false;
|
|
||||||
let renderBread = false;
|
|
||||||
let graphIndex = 1;
|
|
||||||
if (activeGraph == graphIndex && totalGraphs && stakeObj) {
|
|
||||||
renderStake = true;
|
|
||||||
}
|
|
||||||
graphIndex++;
|
|
||||||
if (activeGraph == graphIndex && totalGraphs && earningsObj) {
|
|
||||||
renderEarnings = true;
|
|
||||||
}
|
|
||||||
graphIndex++;
|
|
||||||
if (activeGraph == graphIndex && totalGraphs && broadcasterObj) {
|
|
||||||
renderBread = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="stroke" key={obj.seed + "strok"}>
|
|
||||||
{obj.data.reactivationCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: activationColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-reactivationCount-"} icon={"🔌"} subtext={obj.data.reactivationCount + " reactivations"} descriptions={[
|
|
||||||
obj.data.reactivationCount + " Orchestrators reactivated"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.activationCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: activationColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔧"} subtext={obj.data.activationCount + " new orchestrators"} descriptions={[
|
|
||||||
obj.data.activationCount + " orchestrators joined with an initial stake of " + obj.data.activationInitialSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{(obj.data.latestCommission && obj.data.latestCommission.length) ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: updateColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔗"} subtext={obj.data.latestCommission.length + " orchestrators found"} descriptions={[
|
|
||||||
obj.data.latestCommission.length + " orchestrators had a total of " + totalStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT staked to them"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.bondCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: stakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"📈"} subtext={obj.data.bondCount + " new delegators"} descriptions={[
|
|
||||||
obj.data.bondCount + " accounts delegated for the first time for a total of " + obj.data.bondStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.unbondCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: unbondColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"📉"} subtext={obj.data.unbondCount + " leaving delegators"} descriptions={[
|
|
||||||
obj.data.unbondCount + " delegators unbonded " + obj.data.unbondStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.rewardCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: rewardColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"⌛"} subtext={obj.data.rewardCount + " reward calls"} descriptions={[
|
|
||||||
obj.data.rewardCount + " reward calls made by orchestrators were worth " + obj.data.rewardAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.claimCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: claimColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🏦"} subtext={obj.data.claimCount + " reward claims"} descriptions={[
|
|
||||||
obj.data.claimRewardSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT and " + obj.data.claimFeeSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH worth of rewards were claimed by delegators"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.withdrawStakeCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: withdrawStakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"💸"} subtext={obj.data.withdrawStakeCount + " withdraw reward calls"} descriptions={[
|
|
||||||
obj.data.withdrawStakeAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT worth of staking rewards were withdrawn to the account of the delegator"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.withdrawFeesCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: withdrawStakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"💸"} subtext={obj.data.withdrawFeesCount + " withdraw fee calls"} descriptions={[
|
|
||||||
obj.data.withdrawFeesAmountSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH worth of transcoding fees were withdrawn to the account of the delegator"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.moveStakeCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: stakeColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🔄"} subtext={obj.data.moveStakeCount + " stake movements"} descriptions={[
|
|
||||||
obj.data.moveStakeSum.toLocaleString({ maximumFractionDigits: 2 }) + " LPT worth of stake was moved between orchestrators"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.winningTicketsReceivedCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: ticketTransferColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🎫"} subtext={obj.data.winningTicketsReceivedCount + " winning tickets"} descriptions={[
|
|
||||||
obj.data.winningTicketsReceivedCount + " winning tickets were sent out by " + obj.data.winningTicketsSent.length + " broadcasters"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}
|
|
||||||
<div className="halfVerticalDivider" />
|
|
||||||
{obj.data.winningTicketsRedeemedCount ?
|
|
||||||
<div className="row">
|
|
||||||
<div className="row" style={{ justifyContent: 'space-between', alignItems: 'stretch', maxWidth: '61.8%', textAlign: 'justify', padding: '0.5em', backgroundColor: ticketRedeemColour, border: '0.1em solid rgba(54, 46, 46, 0.1)' }}>
|
|
||||||
<Ticket seed={obj.seed + "-neworchs-"} icon={"🎟️"} subtext={obj.data.winningTicketsRedeemedCount + " redeemed tickets"} descriptions={[
|
|
||||||
obj.data.winningTicketsRedeemedCount + " winning tickets were redeemed worth " + obj.data.winningTicketsRedeemedSum.toLocaleString({ maximumFractionDigits: 2 }) + " ETH"
|
|
||||||
]} />
|
|
||||||
</div>
|
|
||||||
</div> : null
|
|
||||||
}<div className="halfVerticalDivider" />
|
|
||||||
<div className="verticalDivider" />
|
|
||||||
{renderStake ? stakeObj : null}
|
|
||||||
{renderEarnings ? earningsObj : null}
|
|
||||||
{renderBread ? broadcasterObj : null}
|
|
||||||
<div className="row" style={{ marginTop: '1em', marginBottom: '1em' }}>
|
|
||||||
{totalGraphs > 1 ?
|
|
||||||
<Pagination page={activeGraph} onChange={setGraph} total={totalGraphs} siblings={1} initialPage={1} />
|
|
||||||
: null}
|
|
||||||
</div>
|
|
||||||
<div className="row">
|
|
||||||
<div className="strokeSmollLeft fullMargin" style={{ paddingBottom: 0, marginBottom: 0, height: '80vh' }}>
|
|
||||||
<div className="row">
|
|
||||||
<h3>{sortedList.length} Delegators</h3>
|
|
||||||
</div>
|
|
||||||
<div className="content-wrapper">
|
|
||||||
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}>
|
|
||||||
<div className="overflow-content" style={{ cursor: 'grab', maxHeight: '300px' }}>
|
|
||||||
{
|
|
||||||
sortedList.map(function (orch, i) {
|
|
||||||
const tmp = i - ((activePage - 1) * itemsPerPage);
|
|
||||||
if (tmp >= 0 && tmp < itemsPerPage) {
|
|
||||||
let thisCommission = null;
|
|
||||||
let thisStake = null;
|
|
||||||
let thisEarnings = null;
|
|
||||||
|
|
||||||
for (const obj of ticketList) {
|
|
||||||
if (obj.address == orch.address) {
|
|
||||||
thisEarnings = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const obj of commissionList) {
|
|
||||||
if (obj.address == orch.address) {
|
|
||||||
thisCommission = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (const obj of stakeList) {
|
|
||||||
if (obj.address == orch.address) {
|
|
||||||
thisStake = obj;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let thisScore = null;
|
|
||||||
if (thisScores && thisScores.scores) {
|
|
||||||
thisScore = thisScores.scores[orch.address];
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className='stroke' key={obj.seed + orch.address + i}>
|
|
||||||
<Winner
|
|
||||||
thisScore={thisScore}
|
|
||||||
totalEarnings={obj.data.winningTicketsReceivedSum}
|
|
||||||
thisEarnings={thisEarnings}
|
|
||||||
totalStake={totalStakeSum}
|
|
||||||
thisStake={thisStake}
|
|
||||||
thisCommission={thisCommission}
|
|
||||||
address={orch.address}
|
|
||||||
thisIndex={i + 1}
|
|
||||||
seed={obj.seed + "win" + orch.address + i}
|
|
||||||
/>
|
|
||||||
<div className="verticalDivider" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</ScrollContainer>
|
|
||||||
</div>
|
|
||||||
<div className="row" style={{ marginTop: '1em', marginBottom: '1em' }}>
|
|
||||||
{totalPages > 1 ?
|
|
||||||
<Pagination page={activePage} onChange={setPage} total={totalPages} siblings={1} initialPage={1} />
|
|
||||||
: null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="verticalDivider" />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default WinnerMonth;
|
|
@ -91,7 +91,7 @@ const Winner = (obj) => {
|
|||||||
return (
|
return (
|
||||||
<div className="stroke hostInfo" style={{ padding: '1em', cursor: 'grab' }} >
|
<div className="stroke hostInfo" style={{ padding: '1em', cursor: 'grab' }} >
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="strokeSmollLeft" style={{ marginLeft: '0.2em', whiteSpace:'nowrap' }} >
|
<div className="strokeSmollLeft" style={{ marginLeft: '0.2em', whiteSpace: 'nowrap' }} >
|
||||||
<h3>{obj.thisIndex}</h3>
|
<h3>{obj.thisIndex}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="rowAlignLeft">
|
<div className="rowAlignLeft">
|
||||||
@ -110,7 +110,7 @@ const Winner = (obj) => {
|
|||||||
<div className="rowAlignRight" >
|
<div className="rowAlignRight" >
|
||||||
<span>({((obj.thisEarnings.sum / obj.totalEarnings) * 100).toFixed(2)} %)</span>
|
<span>({((obj.thisEarnings.sum / obj.totalEarnings) * 100).toFixed(2)} %)</span>
|
||||||
</div>
|
</div>
|
||||||
</div> : null
|
</div> : <div className="strokeSmollLeft" style={{ minWidth: '100px' }} />
|
||||||
}
|
}
|
||||||
{obj.thisStake ?
|
{obj.thisStake ?
|
||||||
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
|
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
|
||||||
@ -123,7 +123,7 @@ const Winner = (obj) => {
|
|||||||
<div className="rowAlignRight" >
|
<div className="rowAlignRight" >
|
||||||
<span>({((obj.thisStake.totalStake / obj.totalStake) * 100).toFixed(2)} %)</span>
|
<span>({((obj.thisStake.totalStake / obj.totalStake) * 100).toFixed(2)} %)</span>
|
||||||
</div>
|
</div>
|
||||||
</div> : null
|
</div> : <div className="strokeSmollLeft" style={{ minWidth: '100px' }} />
|
||||||
}
|
}
|
||||||
{obj.thisCommission ?
|
{obj.thisCommission ?
|
||||||
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
|
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
|
||||||
@ -136,7 +136,7 @@ const Winner = (obj) => {
|
|||||||
<div className="rowAlignRight" >
|
<div className="rowAlignRight" >
|
||||||
<span>{obj.thisCommission.feeCommission.toFixed(2)}% Fee</span>
|
<span>{obj.thisCommission.feeCommission.toFixed(2)}% Fee</span>
|
||||||
</div>
|
</div>
|
||||||
</div> : null
|
</div> : <div className="strokeSmollLeft" style={{ minWidth: '100px' }} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
54
src/pages/MonthlyStats.js
Normal file
54
src/pages/MonthlyStats.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import MonthlyFactoids from '../components/MonthlyFactoids';
|
||||||
|
import MonthlyGraphs from '../components/MonthlyGraphs';
|
||||||
|
import MonthlyOrchestrators from '../components/MonthlyOrchestrators';
|
||||||
|
|
||||||
|
import { Pagination } from "@mantine/core";
|
||||||
|
|
||||||
|
const MonthlyStats = (obj) => {
|
||||||
|
const [activePage, setPage] = useState(1);
|
||||||
|
const totalPages = 3;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="stroke" key={obj.seed + "menu"}>
|
||||||
|
<div className="verticalDivider" />
|
||||||
|
<div className="row">
|
||||||
|
{
|
||||||
|
activePage == 1 ? <h4>Summary</h4> : null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
activePage == 2 ? <h4>Graphs</h4> : null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
activePage == 3 ? <h3>orchestrators</h3> : null
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div className="verticalDivider" />
|
||||||
|
{
|
||||||
|
activePage == 1 ? <MonthlyFactoids
|
||||||
|
data={obj.data}
|
||||||
|
seed={"factoids" + obj.data.year + "-" + obj.data.month + "-" + obj.data.total}
|
||||||
|
/> : null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
activePage == 2 ? <MonthlyGraphs
|
||||||
|
data={obj.data}
|
||||||
|
seed={"graphs" + obj.data.year + "-" + obj.data.month + "-" + obj.data.total}
|
||||||
|
/> : null
|
||||||
|
}
|
||||||
|
{
|
||||||
|
activePage == 3 ? <MonthlyOrchestrators
|
||||||
|
data={obj.data}
|
||||||
|
seed={"orchestrators" + obj.data.year + "-" + obj.data.month + "-" + obj.data.total}
|
||||||
|
/> : null
|
||||||
|
}
|
||||||
|
<div className="verticalDivider" />
|
||||||
|
<div className="row" style={{ marginTop: '0.3em', marginBottom: '0.3em' }}>
|
||||||
|
<Pagination page={activePage} onChange={setPage} total={totalPages} siblings={1} initialPage={1} />
|
||||||
|
</div>
|
||||||
|
<div className="verticalDivider" />
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MonthlyStats;
|
@ -1,6 +1,5 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, } from 'react';
|
||||||
import ScrollContainer from "react-indiana-drag-scroll";
|
import ScrollContainer from "react-indiana-drag-scroll";
|
||||||
import Address from "./OrchAddressViewer";
|
|
||||||
import { Pagination } from "@mantine/core";
|
import { Pagination } from "@mantine/core";
|
||||||
|
|
||||||
const itemsPerPage = 10;
|
const itemsPerPage = 10;
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState } from 'react'
|
||||||
import '../style.css';
|
import '../style.css';
|
||||||
import { Navigate } from "react-router-dom";
|
import { Navigate } from "react-router-dom";
|
||||||
import { useSelector, useDispatch } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
import { Accordion } from '@mantine/core';
|
import { Accordion } from '@mantine/core';
|
||||||
import ScrollContainer from 'react-indiana-drag-scroll';
|
import MonthlyStats from './MonthlyStats';
|
||||||
import WinnerMonth from '../components/WinnerMonth';
|
|
||||||
// import Graphs from '../components/Graphs';
|
|
||||||
|
|
||||||
const Stats = (obj) => {
|
const Stats = (obj) => {
|
||||||
const livepeer = useSelector((state) => state.livepeerstate);
|
const livepeer = useSelector((state) => state.livepeerstate);
|
||||||
const [redirectToHome, setRedirectToHome] = useState(false);
|
const [redirectToHome, setRedirectToHome] = useState(false);
|
||||||
const [removeOnlyStakers, setRemoveOnlyStakers] = useState(false);
|
|
||||||
|
|
||||||
console.log("Rendering Stats Viewer");
|
console.log("Rendering Stats Viewer");
|
||||||
|
|
||||||
@ -29,14 +26,6 @@ const Stats = (obj) => {
|
|||||||
</button>
|
</button>
|
||||||
<h4 className="rowAlignLeft withWrap showNeverOnMobile">Statistics</h4>
|
<h4 className="rowAlignLeft withWrap showNeverOnMobile">Statistics</h4>
|
||||||
</div>
|
</div>
|
||||||
{/* <div className='rowAlignRight'>
|
|
||||||
<p>Filter</p>
|
|
||||||
<div className="toggle-container" onClick={() => setRemoveOnlyStakers(!removeOnlyStakers)}>
|
|
||||||
<div className={`dialog-button ${removeOnlyStakers ? "" : "disabled"}`}>
|
|
||||||
{removeOnlyStakers ? "Show" : "Hide"}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
</div>
|
</div>
|
||||||
<div id='bodyContent'>
|
<div id='bodyContent'>
|
||||||
<div className="mainContent">
|
<div className="mainContent">
|
||||||
@ -44,21 +33,40 @@ const Stats = (obj) => {
|
|||||||
<div className="row" style={{ width: '100%', height: '100%' }}>
|
<div className="row" style={{ width: '100%', height: '100%' }}>
|
||||||
<div className="stroke roundedOpaque onlyVerticalScroll" style={{ width: '40vw', minWidth: '400px', height: 'calc( 100vh - 50px - 2em)', marginTop: '2em' }}>
|
<div className="stroke roundedOpaque onlyVerticalScroll" style={{ width: '40vw', minWidth: '400px', height: 'calc( 100vh - 50px - 2em)', marginTop: '2em' }}>
|
||||||
<div className="content-wrapper" style={{ width: '100%' }}>
|
<div className="content-wrapper" style={{ width: '100%' }}>
|
||||||
<ScrollContainer activationDistance={1} className="overflow-container" hideScrollbars={false}>
|
<div className="overflow-container">
|
||||||
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}>
|
<div className="overflow-content" style={{ padding: 0 }}>
|
||||||
<div className="flexContainer forceWrap" >
|
<div className="flexContainer forceWrap" >
|
||||||
<Accordion initialItem={0} className="stroke"
|
<Accordion initialItem={0} className="stroke"
|
||||||
|
style={{ width: '100%', alignItems: 'stretch' }}
|
||||||
styles={{
|
styles={{
|
||||||
item: { padding: 0 },
|
item: { padding: 0, width: '100%', alignItems: 'stretch' },
|
||||||
itemOpened: { padding: 0 },
|
itemOpened: { padding: 0, width: '100%', alignItems: 'stretch' },
|
||||||
itemTitle: { padding: 0, paddingTop: '1em', paddingBottom: '1em' },
|
itemTitle: {
|
||||||
control: { padding: 0 },
|
color: 'rgba(218, 218, 218, 0.9)',
|
||||||
label: { padding: 0 },
|
padding: 0, width: '100%',
|
||||||
icon: { padding: 0 },
|
},
|
||||||
content: { padding: 0, paddingTop: '1em', paddingBottom: '1em' },
|
control: {
|
||||||
contentInner: { padding: 0 },
|
color: 'rgba(218, 218, 218, 0.9)',
|
||||||
|
padding: 0, margin: 0, height: '100%',
|
||||||
|
backgroundColor: 'rgba(56, 56, 56, 0.8)',
|
||||||
|
boxShadow: 'inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05)'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
color: 'rgba(218, 218, 218, 0.9)',
|
||||||
|
padding: '1em', width: '100%',
|
||||||
|
backgroundColor: 'rgba(56, 56, 56, 0.8)',
|
||||||
|
boxShadow: 'inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05)'
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
padding: 0, margin: 0,
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
padding: 0, alignItems: 'stretch', width: '100%', height: '100%',
|
||||||
|
backgroundColor: 'rgba(56, 56, 56, 0.3)',
|
||||||
|
boxShadow: 'inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05)'
|
||||||
|
},
|
||||||
|
contentInner: { padding: 0, width: '100%', height: '100%' },
|
||||||
}}>
|
}}>
|
||||||
{/* <Graphs commissions={livepeer.allCommissions} stakes={livepeer.allTotalStakes} /> */}
|
|
||||||
{
|
{
|
||||||
livepeer.monthlyStats.slice(0).reverse().map(function (data, i) {
|
livepeer.monthlyStats.slice(0).reverse().map(function (data, i) {
|
||||||
let thisMonth = "";
|
let thisMonth = "";
|
||||||
@ -89,14 +97,17 @@ const Stats = (obj) => {
|
|||||||
thisMonth = "December";;
|
thisMonth = "December";;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const title = data.year + "-" + thisMonth + ": " + data.winningTicketsReceived.length + " orchestrators earned " + data.winningTicketsReceivedSum.toFixed(2) + " Eth";
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion.Item
|
<Accordion.Item
|
||||||
label={data.year + "-" + thisMonth + ": " + data.winningTicketsReceived.length + " orchestrators earned " + data.winningTicketsReceivedSum.toFixed(2) + " Eth"}
|
label={title}
|
||||||
|
icon={"🔄"}
|
||||||
className="stroke"
|
className="stroke"
|
||||||
|
style={{ width: '100%', alignItems: 'stretch' }}
|
||||||
key={"accord" + i + data.year + "-" + data.month + "-" + data.total}>
|
key={"accord" + i + data.year + "-" + data.month + "-" + data.total}>
|
||||||
<WinnerMonth
|
<MonthlyStats
|
||||||
data={data}
|
data={data}
|
||||||
removeOnlyStakers={removeOnlyStakers}
|
|
||||||
seed={"win" + i + data.year + "-" + data.month + "-" + data.total}
|
seed={"win" + i + data.year + "-" + data.month + "-" + data.total}
|
||||||
/>
|
/>
|
||||||
</Accordion.Item>
|
</Accordion.Item>
|
||||||
@ -106,7 +117,6 @@ const Stats = (obj) => {
|
|||||||
</Accordion>
|
</Accordion>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ScrollContainer>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -114,6 +124,7 @@ const Stats = (obj) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div >
|
</div >
|
||||||
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +228,14 @@ svg {
|
|||||||
border-radius: 1em;
|
border-radius: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.insetEffect {
|
||||||
|
background-color: rgba(206, 206, 206, 0.26);
|
||||||
|
-webkit-box-shadow: inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05);
|
||||||
|
-moz-box-shadow: inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05);
|
||||||
|
box-shadow: inset 3px 3px 12px 2px rgba(62, 62, 104, 0.05);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.smallTxt {
|
.smallTxt {
|
||||||
font-size: small;
|
font-size: small;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user