LivepeerEvents/src/components/WinnerMonth.js

355 lines
11 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from 'react'
import { useSelector } from 'react-redux';
import { VictoryPie } from 'victory';
import Winner from '../components/WinnerStat';
import {
getOrchestratorScores
} from "../actions/livepeer";
const WinnerMonth = (obj) => {
const livepeer = useSelector((state) => state.livepeerstate);
const [thisScores, setThisScores] = useState(null);
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) {
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, 14) + "..");
}
break;
}
}
}
return (address.substring(0, 14) + "..");
}
// 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.04) {
otherSum += thisTicket.totalStake;
} else {
pieList.push({
address: getName(thisTicket.address),
sum: thisTicket.totalStake
});
}
}
pieList.push({
address: "Other",
sum: otherSum
});
stakeObj = <div className="stroke">
<h4>Stake Distribution</h4>
<VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} 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={{
backgroundColor: 'rgba(122, 128, 127, 0.4)',
data: {
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
},
labels: {
fontSize: 10, zIndex: 999
}
}}
labelPosition="centroid"
labelPlacement="parallel"
/>
</div>;
} 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;
let thisVal = null;
// Find current O with most ticket wins in Eth
while (ticketIdx2 >= 0) {
const currentOrch = orchList[ticketIdx2];
thisVal = currentOrch.sum;
if (!thisVal) {
ticketIdx2 -= 1;
continue;
}
if (thisVal > largestValue) {
largestIdx = ticketIdx2;
largestValue = thisVal;
}
ticketIdx2 -= 1;
}
// Else try to sort by stake
if (!thisVal) {
ticketIdx2 = orchList.length - 1;
while (ticketIdx2 >= 0) {
const currentOrch = orchList[ticketIdx2];
thisVal = currentOrch.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);
}
}
// 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.03) {
otherSum += thisTicket.sum;
} else {
pieList.push({
address: getName(thisTicket.address),
sum: thisTicket.sum
});
}
}
pieList.push({
address: "Other",
sum: otherSum
});
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"
colorScale={[
"#003f5c",
"#2f4b7c",
"#665191",
"#ff7c43",
"#ffa600",
"#5c3446",
"#83424e",
"#a6544e",
"#c16d46",
"#d18d3c",
"#d3b136",
"#c5d843",
"#a3ff69",
]}
style={{
backgroundColor: 'rgba(122, 128, 127, 0.4)',
data: {
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
},
labels: {
fontSize: 10, zIndex: 999
}
}}
labelPosition="centroid"
labelPlacement="parallel"
/>
</div>;
}
return (
<div className="stroke" key={obj.seed + "strok"}>
{obj.data.reactivationCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🔌 {obj.data.reactivationCount} Orchestrators reactivated</p>
</div> : null
}
{obj.data.activationCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🔧 {obj.data.activationCount} Orchestrator joined with an initial stake of {obj.data.activationInitialSum.toFixed(2)} LPT</p>
</div> : null
}
{obj.data.unbondCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">📉 {obj.data.unbondCount} delegators unbonded {obj.data.unbondStakeSum.toFixed(2)} LPT</p>
</div> : null
}
{obj.data.rewardCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll"> {obj.data.rewardCount} reward calls were made worth {obj.data.rewardAmountSum.toFixed(2)} LPT</p>
</div> : null
}
{obj.data.claimCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">💸 {obj.data.claimRewardSum.toFixed(2)} LPT and {obj.data.claimFeeSum.toFixed(2)} ETH rewards were claimed by {obj.data.claimCount} delegators</p>
</div> : null
}
{obj.data.withdrawStakeCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🏦 {obj.data.withdrawStakeAmountSum.toFixed(2)} LPT worth of staking rewards were withdrawn by {obj.data.withdrawStakeCount} delegators</p>
</div> : null
}
{obj.data.withdrawFeesCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🏦 {obj.data.withdrawFeesAmountSum.toFixed(2)} ETH worth of transcoding fees were withdrawn by {obj.data.withdrawFeesCount} delegators </p>
</div> : null
}
{obj.data.bondCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">📈 {obj.data.bondCount} accounts delegated for the first time for a total of {obj.data.bondStakeSum.toFixed(2)} LPT</p>
</div> : null
}
{obj.data.moveStakeCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🔄 {obj.data.moveStakeSum.toFixed(2)} LPT stake got moved around in {obj.data.moveStakeCount} transactions </p>
</div> : null
}
{obj.data.winningTicketsReceivedCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🎫 {obj.data.winningTicketsReceivedCount} winning tickets were sent out worth {obj.data.winningTicketsReceivedSum.toFixed(2)} ETH</p>
</div> : null
}
{obj.data.winningTicketsRedeemedCount ?
<div className="rowAlignLeft">
<p className="darkTextSmoll">🎟 {obj.data.winningTicketsRedeemedCount} winning tickets were redeemed worth {obj.data.winningTicketsRedeemedSum.toFixed(2)} ETH</p>
</div> : null
}
<div className="verticalDivider" />
{stakeObj}
{earningsObj}
<div className="flexContainer forceWrap">
{
sortedList.map(function (orch, i) {
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) {
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>
)
})
}
</div>
<div className="verticalDivider" />
</div>
)
}
export default WinnerMonth;