This commit is contained in:
Marco van Dijk 2022-04-21 19:27:03 +02:00
parent 9b4e3455f3
commit 31c41b2673
9 changed files with 311 additions and 211 deletions

View File

@ -39,6 +39,8 @@ const fs = require('fs');
// Used for the livepeer thegraph API // Used for the livepeer thegraph API
import { request, gql } from 'graphql-request'; import { request, gql } from 'graphql-request';
import MonthlyStat from "../models/monthlyStat"; import MonthlyStat from "../models/monthlyStat";
import CommissionDataPoint from "../models/CommissionDataPoint";
import TotalStakeDataPoint from "../models/TotalStakeDataPoint";
// Gets ETH, LPT and other coin info // Gets ETH, LPT and other coin info
let CoinMarketCap = require('coinmarketcap-api'); let CoinMarketCap = require('coinmarketcap-api');
@ -270,7 +272,7 @@ const updateMonthlyReward = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly Reward stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly Reward stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -303,7 +305,7 @@ const updateMonthlyClaim = async function (blockTime, fees, rewards) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly Claim stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly Claim stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -338,7 +340,7 @@ const updateMonthlyWithdrawStake = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly WithdrawStake stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly WithdrawStake stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -371,7 +373,7 @@ const updateMonthlyWithdrawFees = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly WithdrawFees stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly WithdrawFees stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -404,7 +406,7 @@ const updateMonthlyNewDelegator = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly new Delegator stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly new Delegator stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -437,7 +439,7 @@ const updateMonthlyUnbond = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly new Unbond stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly new Unbond stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -501,7 +503,7 @@ const updateMonthlyActivation = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly new activation stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly new activation stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -534,7 +536,7 @@ const updateMonthlyMoveStake = async function (blockTime, amount) {
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly stake movement stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly stake movement stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -567,7 +569,7 @@ const updateMonthlyTicketReceived = async function (blockTime, amount, from, to)
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly ticket received stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly ticket received stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -685,7 +687,7 @@ const updateMonthlyTicketRedeemed = async function (blockTime, amount, address)
var dateObj = new Date(0); var dateObj = new Date(0);
dateObj.setUTCSeconds(blockTime); dateObj.setUTCSeconds(blockTime);
// Determine year, month and name // Determine year, month and name
const thisMonth = dateObj.getMonth() ; const thisMonth = dateObj.getMonth();
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
console.log("Updating monthly ticket redeemed stats for " + thisYear + "-" + thisMonth); console.log("Updating monthly ticket redeemed stats for " + thisYear + "-" + thisMonth);
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
@ -1087,8 +1089,12 @@ const syncEvents = function (toBlock) {
let size = events.length; let size = events.length;
console.log("Parsing " + size + " events"); console.log("Parsing " + size + " events");
if (!size) { if (!size) {
if (toBlock == 'latest') {
lastBlockEvents = latestBlockInChain;
} else {
lastBlockEvents = toBlock; lastBlockEvents = toBlock;
} }
}
for (const event of events) { for (const event of events) {
if (event.blockNumber > lastBlockEvents) { if (event.blockNumber > lastBlockEvents) {
lastBlockEvents = event.blockNumber; lastBlockEvents = event.blockNumber;
@ -1141,8 +1147,12 @@ const syncTickets = function (toBlock) {
let size = events.length; let size = events.length;
console.log("Parsing " + size + " tickets"); console.log("Parsing " + size + " tickets");
if (!size) { if (!size) {
if (toBlock == 'latest') {
lastBlockTickets = latestBlockInChain;
} else {
lastBlockTickets = toBlock; lastBlockTickets = toBlock;
} }
}
for (const event of events) { for (const event of events) {
if (event.blockNumber > lastBlockTickets) { if (event.blockNumber > lastBlockTickets) {
lastBlockTickets = event.blockNumber; lastBlockTickets = event.blockNumber;
@ -1247,6 +1257,8 @@ const initSync = async function () {
address: 1, address: 1,
fees: 1, fees: 1,
rewards: 1, rewards: 1,
startRound: 1,
endRound: 1,
transactionHash: 1, transactionHash: 1,
blockNumber: 1, blockNumber: 1,
blockTime: 1, blockTime: 1,
@ -1373,6 +1385,7 @@ const handleSync = async function () {
console.log("Latest L2 Eth block changed to " + latestBlockInChain); console.log("Latest L2 Eth block changed to " + latestBlockInChain);
} else { } else {
// If there are no new blocks, wait for 10 seconds before retrying // If there are no new blocks, wait for 10 seconds before retrying
console.log("No new blocks. Sleeping for 10 seconds...");
await sleep(10000); await sleep(10000);
continue; continue;
} }
@ -1381,15 +1394,15 @@ const handleSync = async function () {
// Batch requests when sync is large, mark if we are going to reach latestBlockInChain in this round // Batch requests when sync is large, mark if we are going to reach latestBlockInChain in this round
let getFinalTickets = false; let getFinalTickets = false;
let toTickets = 'latest'; let toTickets = 'latest';
if (latestBlock - lastBlockTickets > 100000) { if (latestBlock - lastBlockTickets > 1000000) {
toTickets = lastBlockTickets + 100000; toTickets = lastBlockTickets + 1000000;
} else { } else {
getFinalTickets = true; getFinalTickets = true;
} }
let getFinalEvents = false; let getFinalEvents = false;
let toEvents = 'latest'; let toEvents = 'latest';
if (latestBlock - lastBlockEvents > 100000) { if (latestBlock - lastBlockEvents > 1000000) {
toEvents = lastBlockEvents + 100000; toEvents = lastBlockEvents + 1000000;
} else { } else {
getFinalEvents = true; getFinalEvents = true;
} }
@ -1404,8 +1417,8 @@ const handleSync = async function () {
} else if (!getFinalEvents) { } else if (!getFinalEvents) {
// Start next batch for events // Start next batch for events
toEvents = 'latest'; toEvents = 'latest';
if (latestBlock - lastBlockEvents > 100000) { if (latestBlock - lastBlockEvents > 1000000) {
toEvents = lastBlockEvents + 100000; toEvents = lastBlockEvents + 1000000;
} else { } else {
getFinalEvents = true; getFinalEvents = true;
} }
@ -1416,8 +1429,8 @@ const handleSync = async function () {
} else if (!getFinalTickets) { } else if (!getFinalTickets) {
// Start next batch for tickets // Start next batch for tickets
toTickets = 'latest'; toTickets = 'latest';
if (latestBlock - lastBlockTickets > 100000) { if (latestBlock - lastBlockTickets > 1000000) {
toTickets = lastBlockTickets + 100000; toTickets = lastBlockTickets + 1000000;
} else { } else {
getFinalTickets = true; getFinalTickets = true;
} }
@ -1635,7 +1648,7 @@ const mutateNewCommissionRates = async function (address, feeCommission, rewardC
feeCommission = (100 - (feeCommission / 10000)).toFixed(2); feeCommission = (100 - (feeCommission / 10000)).toFixed(2);
// Create new data point // Create new data point
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
const dbObj = new Event({ const dbObj = new CommissionDataPoint({
address: address, address: address,
feeCommission: feeCommission, feeCommission: feeCommission,
rewardCommission: rewardCommission, rewardCommission: rewardCommission,
@ -1698,7 +1711,7 @@ const mutateNewGlobalStake = async function (address, globalStake) {
const thisYear = dateObj.getFullYear(); const thisYear = dateObj.getFullYear();
// Create new data point // Create new data point
if (!CONF_DISABLE_DB) { if (!CONF_DISABLE_DB) {
const dbObj = new Event({ const dbObj = new TotalStakeDataPoint({
address: address, address: address,
totalStake: globalStake, totalStake: globalStake,
timestamp: now timestamp: now
@ -2486,12 +2499,10 @@ const mutateTestScoresToDB = async function (scoreObj, month, year) {
} }
// Immediately mutate Monthly statistics object // Immediately mutate Monthly statistics object
const doc = await MonthlyStat.findOneAndUpdate({ const doc = await MonthlyStat.findOneAndUpdate({
year: thisYear, year: year,
month: thisMonth month: month
}, { }, {
$set: {
testScores: scoreObj testScores: scoreObj
}
}, { }, {
upsert: true, upsert: true,
new: true, new: true,
@ -2525,6 +2536,7 @@ const getScoreAtMonthYear = async function (month, year) {
const endTime = parseInt(Date.parse(endString) / 1000) const endTime = parseInt(Date.parse(endString) / 1000)
// Else get it and cache it // Else get it and cache it
const url = "https://leaderboard-serverless.vercel.app/api/aggregated_stats?since=" + startTime + "&until=" + endTime; const url = "https://leaderboard-serverless.vercel.app/api/aggregated_stats?since=" + startTime + "&until=" + endTime;
console.log("Getting new Orchestrator scores for " + year + "-" + month + " @ " + url);
await https.get(url, (res) => { await https.get(url, (res) => {
let body = ""; let body = "";
res.on("data", (chunk) => { res.on("data", (chunk) => {

View File

@ -219,8 +219,12 @@ export const getThreeBoxInfo = async (addr) => {
const response = apiUtil.getThreeBox(addr); const response = apiUtil.getThreeBox(addr);
}; };
export const getOrchestratorScores = (year, month) => async dispatch => { export const getOrchestratorScores = async (year, month) => {
const response = apiUtil.getOrchestratorScores(year, month); const response = await apiUtil.getOrchestratorScores(year, month);
const data = await response.json();
if (response.ok) {
return data;
}
}; };
export const getAllOrchScores = () => async dispatch => { export const getAllOrchScores = () => async dispatch => {

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react' import React, { useState, useEffect } from 'react'
import { useSelector, useDispatch } from 'react-redux'; import { useSelector } from 'react-redux';
import { VictoryPie } from 'victory'; import { VictoryPie } from 'victory';
import Winner from '../components/WinnerStat'; import Winner from '../components/WinnerStat';
import { import {
@ -8,29 +8,18 @@ import {
const WinnerMonth = (obj) => { const WinnerMonth = (obj) => {
const livepeer = useSelector((state) => state.livepeerstate); const livepeer = useSelector((state) => state.livepeerstate);
const dispatch = useDispatch();
const [thisScores, setThisScores] = useState(null); const [thisScores, setThisScores] = useState(null);
useEffect(() => { useEffect(async () => {
const now = new Date().getTime(); if (!obj.data.testScores) {
let wasInCache = false; const freshScore = await getOrchestratorScores(obj.data.year, obj.data.month);
// See if it is cached if (freshScore) {
for (const thisScore of obj.data.testScores) { setThisScores(freshScore);
if (thisScore.year === obj.data.year && thisScore.month === obj.data.month) {
// Check timeout
if (now - thisScore.timestamp < 360000) {
wasInCache = true;
} }
if (!thisScores) { } else {
setThisScores(thisScore); setThisScores(obj.data.testScores);
} }
} }, [obj.data.testScores]);
}
if (!wasInCache) {
dispatch(getOrchestratorScores(obj.year, obj.month));
dispatch(getAllMonthlyStats());
}
}, []);
const getName = (address) => { const getName = (address) => {
let thisDomain = null; let thisDomain = null;
@ -70,12 +59,15 @@ const WinnerMonth = (obj) => {
// Show all orchs (if latestTotalStake exists) or show only those in winningTicketsReceived // Show all orchs (if latestTotalStake exists) or show only those in winningTicketsReceived
let orchList; 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 // Pies for stake overview, if have stake data for that month saved
let stakeObj; let stakeObj;
let totalStakeSum = 0; let totalStakeSum = 0;
if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) { if (obj.data.latestTotalStake && obj.data.latestTotalStake.length) {
orchList = obj.data.latestTotalStake; orchList = [...obj.data.latestTotalStake];
let pieList = []; let pieList = [];
let otherSum = 0; let otherSum = 0;
let ticketIdx = obj.data.latestTotalStake.length - 1; let ticketIdx = obj.data.latestTotalStake.length - 1;
@ -106,8 +98,7 @@ const WinnerMonth = (obj) => {
stakeObj = <div className="stroke"> stakeObj = <div className="stroke">
<h4>Stake Distribution</h4> <h4>Stake Distribution</h4>
<div className="row"> <VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
<VictoryPie padding={100} data={pieList} x="address" y="sum"
sortOrder="descending" sortOrder="descending"
sortKey="sum" sortKey="sum"
colorScale={[ colorScale={[
@ -126,6 +117,7 @@ const WinnerMonth = (obj) => {
"#a3ff69", "#a3ff69",
]} ]}
style={{ style={{
backgroundColor: 'rgba(122, 128, 127, 0.4)',
data: { data: {
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2 fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
}, },
@ -133,12 +125,36 @@ const WinnerMonth = (obj) => {
fontSize: 10, zIndex: 999 fontSize: 10, zIndex: 999
} }
}} /> }} />
</div>
</div>; </div>;
} else { } else {
orchList = obj.data.winningTicketsReceived; 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];
const thisVal = (currentOrch.sum || currentOrch.totalStake);
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 // Pies for earnings overview
let earningsObj; let earningsObj;
if (obj.data.winningTicketsReceived && obj.data.winningTicketsReceived.length) { if (obj.data.winningTicketsReceived && obj.data.winningTicketsReceived.length) {
@ -163,10 +179,9 @@ const WinnerMonth = (obj) => {
sum: otherSum sum: otherSum
}); });
stakeObj = <div className="stroke"> earningsObj = <div className="stroke">
<h4>Stake Distribution</h4> <h4>Earnings Distribution</h4>
<div className="row"> <VictoryPie padding={{ top: 20, bottom: 20, left: 120, right: 120 }} data={pieList} x="address" y="sum"
<VictoryPie padding={100} data={pieList} x="address" y="sum"
sortOrder="descending" sortOrder="descending"
sortKey="sum" sortKey="sum"
colorScale={[ colorScale={[
@ -185,6 +200,7 @@ const WinnerMonth = (obj) => {
"#a3ff69", "#a3ff69",
]} ]}
style={{ style={{
backgroundColor: 'rgba(122, 128, 127, 0.4)',
data: { data: {
fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2 fillOpacity: 0.9, stroke: "#636363", strokeWidth: 2
}, },
@ -192,101 +208,110 @@ const WinnerMonth = (obj) => {
fontSize: 10, zIndex: 999 fontSize: 10, zIndex: 999
} }
}} /> }} />
</div>
</div>; </div>;
} }
return ( return (
<div className="stroke"> <div className="stroke" key={obj.seed + "strok"}>
{stakeObj}
{earningsObj}
{obj.data.reactivationCount ? {obj.data.reactivationCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.reactivationCount} Orchestrator reactivated</p> <p className="darkTextSmoll">🔌 {obj.data.reactivationCount} Orchestrators reactivated</p>
</div> : null </div> : null
} }
{obj.data.activationCount ? {obj.data.activationCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.activationCount} Orchestrator activated with an initial stake of {obj.data.activationInitialSum} LPT</p> <p className="darkTextSmoll">🔧 {obj.data.activationCount} Orchestrator joined with an initial stake of {obj.data.activationInitialSum.toFixed(2)} LPT</p>
</div> : null </div> : null
} }
{obj.data.unbondCount ? {obj.data.unbondCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.unbondCount} delegators unbonded {obj.data.unbondStakeSum} LPT</p> <p className="darkTextSmoll">📉 {obj.data.unbondCount} delegators unbonded {obj.data.unbondStakeSum.toFixed(2)} LPT</p>
</div> : null </div> : null
} }
{obj.data.rewardCount ? {obj.data.rewardCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.rewardCount} reward calls were made worth {obj.data.rewardAmountSum} LPT</p> <p className="darkTextSmoll"> {obj.data.rewardCount} reward calls were made worth {obj.data.rewardAmountSum.toFixed(2)} LPT</p>
</div> : null </div> : null
} }
{obj.data.claimCount ? {obj.data.claimCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.claimCount} reward claims were made worth {obj.data.claimRewardSum} LPT and {obj.data.claimFeeSum} ETH</p> <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 </div> : null
} }
{obj.data.withdrawStakeCount ? {obj.data.withdrawStakeCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.withdrawStakeCount} withdraw stake calls were made worth {obj.data.withdrawStakeAmountSum} LPT</p> <p className="darkTextSmoll">🏦 {obj.data.withdrawStakeAmountSum.toFixed(2)} LPT worth of staking rewards were withdrawn by {obj.data.withdrawStakeCount} delegators</p>
</div> : null </div> : null
} }
{obj.data.withdrawFeesCount ? {obj.data.withdrawFeesCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.withdrawFeesCount} withdraw fees calls were made worth {obj.data.withdrawFeesAmountSum} ETH</p> <p className="darkTextSmoll">🏦 {obj.data.withdrawFeesAmountSum.toFixed(2)} ETH worth of transcoding fees were withdrawn by {obj.data.withdrawFeesCount} delegators </p>
</div> : null </div> : null
} }
{obj.data.bondCount ? {obj.data.bondCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.bondCount} delegators delegated their first stake worth {obj.data.bondStakeSum} LPT</p> <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 </div> : null
} }
{obj.data.moveStakeCount ? {obj.data.moveStakeCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">Stake got moved around {obj.data.moveStakeCount} times worth {obj.data.moveStakeSum} LPT</p> <p className="darkTextSmoll">🔄 {obj.data.moveStakeSum.toFixed(2)} LPT stake got moved around in {obj.data.moveStakeCount} transactions </p>
</div> : null </div> : null
} }
{obj.data.winningTicketsReceivedCount ? {obj.data.winningTicketsReceivedCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.winningTicketsReceivedCount} winning tickets were sent out worth {obj.data.winningTicketsReceivedSum} ETH</p> <p className="darkTextSmoll">🎫 {obj.data.winningTicketsReceivedCount} winning tickets were sent out worth {obj.data.winningTicketsReceivedSum.toFixed(2)} ETH</p>
</div> : null </div> : null
} }
{obj.data.winningTicketsRedeemedCount ? {obj.data.winningTicketsRedeemedCount ?
<div className="row"> <div className="rowAlignLeft">
<p className="darkText">{obj.data.winningTicketsRedeemedCount} winning tickets were redeemed worth {obj.data.winningTicketsRedeemedSum} ETH</p> <p className="darkTextSmoll">🎟 {obj.data.winningTicketsRedeemedCount} winning tickets were redeemed worth {obj.data.winningTicketsRedeemedSum.toFixed(2)} ETH</p>
</div> : null </div> : null
} }
<div className="verticalDivider" />
{stakeObj}
{earningsObj}
<div className="flexContainer forceWrap"> <div className="flexContainer forceWrap">
{ {
orchList.map(function (orch, i) { sortedList.map(function (orch, i) {
let thisCommission = null; let thisCommission = null;
let thisStake = null; let thisStake = null;
let thisEarnings = null; let thisEarnings = null;
for (const obj in obj.data.winningTicketsReceived) {
if (obj.address == orch.address){ for (const obj of ticketList) {
if (obj.address == orch.address) {
thisEarnings = obj; thisEarnings = obj;
} }
} }
for (const obj in obj.data.latestCommission) { for (const obj of commissionList) {
if (obj.address == orch.address){ if (obj.address == orch.address) {
thisCommission = obj; thisCommission = obj;
} }
} }
for (const obj in obj.data.latestTotalStake) { for (const obj of stakeList) {
if (obj.address == orch.address){ if (obj.address == orch.address) {
thisStake = obj; thisStake = obj;
} }
} }
return (<Winner let thisScore = null;
thisScore={thisScores[obj.address]} if (thisScores) {
thisScore = thisScores.scores[orch.address];
}
return (
<div className='stroke' key={obj.seed + orch.address + i}>
<Winner
thisScore={thisScore}
totalEarnings={obj.data.winningTicketsReceivedSum} totalEarnings={obj.data.winningTicketsReceivedSum}
thisEarnings={thisEarnings} thisEarnings={thisEarnings}
totalStake={totalStakeSum} totalStake={totalStakeSum}
thisStake={thisStake} thisStake={thisStake}
thisCommission={thisCommission} thisCommission={thisCommission}
address={orch.address} address={orch.address}
key={orch.address + i} seed={obj.seed + "win" + orch.address + i}
seed={"win" + orch.address + i} />
/>) <div className="verticalDivider" />
</div>
)
}) })
} }
</div> </div>

View File

@ -6,17 +6,47 @@ import { CircularProgressbar } from 'react-circular-progressbar';
import 'react-circular-progressbar/dist/styles.css'; import 'react-circular-progressbar/dist/styles.css';
const Winner = (obj) => { const Winner = (obj) => {
const [thisScore, setThisScore] = useState(0);
const [opened, setOpened] = useState(false); const [opened, setOpened] = useState(false);
useEffect(() => { useEffect(() => {
let score = 0; let score = 0;
let count = 0;
if (obj.thisScore) { if (obj.thisScore) {
score = (obj.thisScore["FRA"].score + obj.thisScore["LAX"].score + obj.thisScore["LON"].score + obj.thisScore["MDW"].score + obj.thisScore["NYC"].score + obj.thisScore["PRG"].score + obj.thisScore["SIN"].score) / 7; if (obj.thisScore["FRA"]) {
count++;
score += obj.thisScore["FRA"].score;
}
if (obj.thisScore["LAX"]) {
count++;
score += obj.thisScore["LAX"].score;
}
if (obj.thisScore["LON"]) {
count++;
score += obj.thisScore["LON"].score;
}
if (obj.thisScore["MDW"]) {
count++;
score += obj.thisScore["MDW"].score;
}
if (obj.thisScore["NYC"]) {
count++;
score += obj.thisScore["NYC"].score;
}
if (obj.thisScore["PRG"]) {
count++;
score += obj.thisScore["PRG"].score;
}
if (obj.thisScore["SIN"]) {
count++;
score += obj.thisScore["SIN"].score;
}
score /= count;
if (obj.thisScore != score) { if (obj.thisScore != score) {
setobj.thisScore(score); setThisScore(score);
} }
} }
}, [obj.stats]); }, [obj.thisScore]);
let scoreObj = null; let scoreObj = null;
if (obj.thisScore) { if (obj.thisScore) {
@ -26,11 +56,11 @@ const Winner = (obj) => {
onClose={() => setOpened(false)} onClose={() => setOpened(false)}
target={ target={
<div className="strokeSmollLeft" style={{ width: '4em', height: '4em', marginLeft: '2em' }} onClick={() => setOpened((o) => !o)} > <div className="strokeSmollLeft" style={{ width: '4em', height: '4em', marginLeft: '2em' }} onClick={() => setOpened((o) => !o)} >
<CircularProgressbar value={obj.thisScore} maxValue={1} text={`${((obj.thisScore * 10).toFixed(1))}`} <CircularProgressbar value={thisScore} maxValue={1} text={`${((thisScore * 10).toFixed(1))}`}
styles={{ styles={{
root: {}, root: {},
path: { path: {
stroke: `rgba(20, 153, 53, ${obj.thisScore})`, stroke: `rgba(20, 153, 53, ${thisScore})`,
strokeLinecap: 'round', strokeLinecap: 'round',
transition: 'stroke-dashoffset 0.5s ease 0s', transition: 'stroke-dashoffset 0.5s ease 0s',
transformOrigin: 'center center', transformOrigin: 'center center',
@ -54,25 +84,36 @@ const Winner = (obj) => {
position="right" position="right"
withArrow withArrow
> >
<ScoreView score={obj.stats.scores[obj.address]} /> <ScoreView score={obj.thisScore} />
</Popover> </Popover>
} }
return ( return (
<div className="stroke hostInfo" style={{ padding: '1em', cursor: 'grab' }} >
<div className="row"> <div className="row">
<div className="rowAlignLeft"> <div className="rowAlignLeft">
<Address address={obj.address} seed={obj.seed} /> <Address address={obj.address} seed={obj.seed} />
</div> </div>
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} > {scoreObj}
</div>
<div className="row">
{obj.thisEarnings ? <div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
<div className="rowAlignLeft" >
<h3>Fees</h3>
</div>
<div className="rowAlignLeft" > <div className="rowAlignLeft" >
<h4>{obj.thisEarnings.sum.toFixed(4)} Eth</h4> <h4>{obj.thisEarnings.sum.toFixed(4)} Eth</h4>
</div> </div>
<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> </div> : null
}
{obj.thisStake ? {obj.thisStake ?
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} > <div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
<div className="rowAlignLeft" >
<h3>Stake</h3>
</div>
<div className="rowAlignLeft" > <div className="rowAlignLeft" >
<h4>{obj.thisStake.totalStake.toFixed(4)} LPT</h4> <h4>{obj.thisStake.totalStake.toFixed(4)} LPT</h4>
</div> </div>
@ -84,6 +125,9 @@ const Winner = (obj) => {
{obj.thisCommission ? {obj.thisCommission ?
<div className="strokeSmollLeft" style={{ minWidth: '100px' }} > <div className="strokeSmollLeft" style={{ minWidth: '100px' }} >
<div className="rowAlignLeft" > <div className="rowAlignLeft" >
<h3>Commission</h3>
</div>
<div className="rowAlignRight" >
<span>{obj.thisCommission.rewardCommission.toFixed(2)}% Reward</span> <span>{obj.thisCommission.rewardCommission.toFixed(2)}% Reward</span>
</div> </div>
<div className="rowAlignRight" > <div className="rowAlignRight" >
@ -91,7 +135,7 @@ const Winner = (obj) => {
</div> </div>
</div> : null </div> : null
} }
{scoreObj} </div>
</div> </div>
) )
} }

View File

@ -39,7 +39,7 @@ const EventButton = (obj) => {
} else if (obj.type == "claim") { } else if (obj.type == "claim") {
eventCaller = obj.eventObj.address; eventCaller = obj.eventObj.address;
eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"💰"} subtext={"delegator claimed"} descriptions={[ eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"💰"} subtext={"delegator claimed"} descriptions={[
(eventObj.data.endRound - eventObj.data.startRound + 1) + " rounds", (obj.eventObj.endRound - obj.eventObj.startRound + 1) + " rounds",
"+" + obj.eventObj.rewards.toFixed(2) + " LPT rewards", "+" + obj.eventObj.rewards.toFixed(2) + " LPT rewards",
"+" + obj.eventObj.fees.toFixed(4) + " Eth fees" "+" + obj.eventObj.fees.toFixed(4) + " Eth fees"
]} /> ]} />
@ -47,9 +47,8 @@ const EventButton = (obj) => {
} else if (obj.type == "withdrawStake") { } else if (obj.type == "withdrawStake") {
eventCaller = obj.eventObj.address; eventCaller = obj.eventObj.address;
eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"🏦"} subtext={"withdrew stake"} descriptions={[ eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"🏦"} subtext={"withdrew stake"} descriptions={[
(eventObj.endRound - eventObj.startRound + 1) + " rounds", obj.eventObj.amount.toFixed(2) + " LPT",
"+" + obj.eventObj.rewards.toFixed(2) + " LPT rewards", "round " + obj.eventObj.round
"+" + obj.eventObj.fees.toFixed(4) + " Eth fees"
]} /> ]} />
eventColour = withdrawStakeColour; eventColour = withdrawStakeColour;
} else if (obj.type == "withdrawFees") { } else if (obj.type == "withdrawFees") {
@ -98,40 +97,40 @@ const EventButton = (obj) => {
eventTo = obj.eventObj.to; eventTo = obj.eventObj.to;
if (eventFrom === "0x0000000000000000000000000000000000000000") { if (eventFrom === "0x0000000000000000000000000000000000000000") {
eventFrom = ""; eventFrom = "";
eventDescription = <Ticket seed={currentTx + "-" + txCounter} icon={"⌛"} subtext={"is now staking"} descriptions={[ eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"⌛"} subtext={"is now staking"} descriptions={[
obj.eventObj.stake.toFixed(2) + " LPT" obj.eventObj.stake.toFixed(2) + " LPT"
]} /> ]} />
} else if (eventFrom === eventTo) { } else if (eventFrom === eventTo) {
eventFrom = ""; eventFrom = "";
eventDescription = <Ticket seed={currentTx + "-" + txCounter} icon={"⌛"} subtext={"changed stake"} descriptions={[ eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"⌛"} subtext={"changed stake"} descriptions={[
obj.eventObj.stake.toFixed(2) + " LPT" obj.eventObj.stake.toFixed(2) + " LPT"
]} /> ]} />
} else { } else {
eventDescription = <Ticket seed={currentTx + "-" + txCounter} icon={"⌛"} subtext={"moved stake"} descriptions={[ eventDescription = <Ticket seed={obj.seed + "-desc-"} icon={"⌛"} subtext={"moved stake"} descriptions={[
obj.eventObj.stake.toFixed(2) + " LPT" obj.eventObj.stake.toFixed(2) + " LPT"
]} /> ]} />
} }
eventColour = stakeColour; eventColour = stakeColour;
} }
if (obj.eventObj.eventFrom === "0x0000000000000000000000000000000000000000") { if (eventFrom === "0x0000000000000000000000000000000000000000") {
obj.eventObj.eventFrom = ""; eventFrom = "";
} }
if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") { if (eventTo === "0x0000000000000000000000000000000000000000") {
obj.eventObj.eventTo = ""; eventTo = "";
} }
if (obj.eventObj.eventTo || obj.eventObj.eventFrom || obj.eventObj.eventCaller) { if (eventTo || eventFrom || eventCaller) {
if (obj.eventObj.eventTo) { if (eventTo) {
eventTo = eventTo =
<EventButtonAddress name="To&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;" address={obj.eventObj.eventTo} setSearchTerm={obj.setSearchTerm} /> <EventButtonAddress name="To&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;" address={eventTo} setSearchTerm={obj.setSearchTerm} />
} }
if (obj.eventObj.eventFrom) { if (eventFrom) {
eventFrom = eventFrom =
<EventButtonAddress name="From&nbsp;&nbsp;:&nbsp;" address={obj.eventObj.eventFrom} setSearchTerm={obj.setSearchTerm} /> <EventButtonAddress name="From&nbsp;&nbsp;:&nbsp;" address={eventFrom} setSearchTerm={obj.setSearchTerm} />
} }
if (obj.eventObj.eventCaller) { if (eventCaller) {
eventCaller = eventCaller =
<EventButtonAddress name="Caller&nbsp;:&nbsp;" address={obj.eventObj.eventCaller} setSearchTerm={obj.setSearchTerm} /> <EventButtonAddress name="Caller&nbsp;:&nbsp;" address={eventCaller} setSearchTerm={obj.setSearchTerm} />
} }
} }

View File

@ -34,7 +34,9 @@ const EventViewer = (obj) => {
let filtered = 0; let filtered = 0;
let hidden = 0; let hidden = 0;
let prevBlock = 0; let prevBlock = 0;
let limitShown = obj.events.length + obj.tickets.length; let limitShown = obj.updateEvents.length + obj.rewardEvents.length + obj.claimEvents.length +
obj.withdrawStakeEvents.length + obj.withdrawFeesEvents.length + obj.activateEvents.length +
obj.stakeEvents.length + obj.unbondEvents.length + obj.transferTicketEvents.length + obj.redeemTicketEvents.length;
let filterActivatedColour; let filterActivatedColour;
filterActivatedColour = filterActivated ? activationColour : greyColour; filterActivatedColour = filterActivated ? activationColour : greyColour;
@ -429,7 +431,7 @@ const EventViewer = (obj) => {
if (unfiltered < obj.maxAmount) { if (unfiltered < obj.maxAmount) {
unfiltered++; unfiltered++;
if (prevBlock === thisEvent.transactionBlock) { if (prevBlock === thisEvent.blockNumber) {
eventList.push(<EventButton eventList.push(<EventButton
key={thisEvent.transactionHash + unfiltered} key={thisEvent.transactionHash + unfiltered}
seed={thisEvent.transactionHash + unfiltered} seed={thisEvent.transactionHash + unfiltered}
@ -438,14 +440,14 @@ const EventViewer = (obj) => {
setSearchTerm={obj.setSearchTerm} setSearchTerm={obj.setSearchTerm}
/>); />);
} else { } else {
prevBlock = thisEvent.transactionBlock; prevBlock = thisEvent.blockNumber;
eventList.push(<EventButton eventList.push(<EventButton
key={thisEvent.transactionHash + unfiltered} key={thisEvent.transactionHash + unfiltered}
seed={thisEvent.transactionHash + unfiltered} seed={thisEvent.transactionHash + unfiltered}
eventObj={thisEvent} eventObj={thisEvent}
type={latestType} type={latestType}
isFirstOfBlock={prevBlock} isFirstOfBlock={prevBlock}
time={thisEvent.transactionTime} time={thisEvent.blockTime}
setSearchTerm={obj.setSearchTerm} setSearchTerm={obj.setSearchTerm}
/>); />);
} }
@ -501,6 +503,7 @@ const EventViewer = (obj) => {
hideScrollbars={false} onEndScroll={updateOnScroll} ref={listInnerRef}> hideScrollbars={false} onEndScroll={updateOnScroll} ref={listInnerRef}>
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}> <div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}>
<div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} > <div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} >
<div className="verticalDivider" />
{eventList} {eventList}
<div className="verticalDivider" /> <div className="verticalDivider" />
{showMoreButton} {showMoreButton}

View File

@ -4,9 +4,12 @@ import {
getVisitorStats getVisitorStats
} from "../actions/user"; } from "../actions/user";
import { import {
getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo, getTickets, getQuotes, getBlockchainData, getCurrentOrchestratorInfo,
getAllEnsDomains, getAllEnsInfo, getAllThreeBoxInfo, getAllOrchScores, getAllOrchInfo, getAllEnsDomains, getAllEnsInfo, getAllThreeBoxInfo, getAllOrchScores, getAllOrchInfo,
getAllDelInfo, getAllMonthlyStats getAllDelInfo, getAllMonthlyStats, getAllUpdateEvents, getAllRewardEvents,
getAllClaimEvents, getAllWithdrawStakeEvents, getAllWithdrawFeesEvents,
getAllTransferTicketEvents, getAllRedeemTicketEvents, getAllActivateEvents,
getAllUnbondEvents, getAllStakeEvents,
} from "../actions/livepeer"; } from "../actions/livepeer";
import { login } from "../actions/session"; import { login } from "../actions/session";

View File

@ -58,7 +58,7 @@ const Stats = (obj) => {
contentInner: { padding: 0 }, contentInner: { padding: 0 },
}}> }}>
{ {
livepeer.monthlyStats.map(function (data) { livepeer.monthlyStats.slice(0).reverse().map(function (data, i) {
let thisMonth = ""; let thisMonth = "";
let monthAsNum = data.month; let monthAsNum = data.month;
if (monthAsNum == 0) { if (monthAsNum == 0) {
@ -91,10 +91,11 @@ const Stats = (obj) => {
<Accordion.Item <Accordion.Item
label={data.year + "-" + thisMonth + ": " + data.winningTicketsReceived.length + " orchestrators earned " + data.winningTicketsReceivedSum.toFixed(2) + " Eth"} label={data.year + "-" + thisMonth + ": " + data.winningTicketsReceived.length + " orchestrators earned " + data.winningTicketsReceivedSum.toFixed(2) + " Eth"}
className="stroke" className="stroke"
key={data.year + "-" + data.month + "-" + data.total}> key={"accord" + i + data.year + "-" + data.month + "-" + data.total}>
<WinnerMonth <WinnerMonth
data={data} data={data}
removeOnlyStakers={removeOnlyStakers} removeOnlyStakers={removeOnlyStakers}
seed={"win" + i + data.year + "-" + data.month + "-" + data.total}
/> />
</Accordion.Item> </Accordion.Item>
) )

View File

@ -200,6 +200,15 @@ svg {
text-shadow: 0.5px 0.5px 0.8px #5a5663; text-shadow: 0.5px 0.5px 0.8px #5a5663;
} }
.darkTextSmoll {
margin: 0;
padding: 0;
color: rgba(0, 0, 0, 0.875);
text-shadow: 0.5px 0.5px 0.8px #5a5663;
font-weight: normal;
font-size: small;
}
.hostInfo { .hostInfo {
cursor: default; cursor: default;
text-align: start; text-align: start;