diff --git a/dumps/orchInfo.json b/dumps/orchInfo.json new file mode 100644 index 0000000..ebe560b --- /dev/null +++ b/dumps/orchInfo.json @@ -0,0 +1,57 @@ +{ + "id": "0x1a196b031ea1a74a53ecbe6148772648e02f9d51", + "activationRound": "2467", + "deactivationRound": "57896044618658097711785492504343953926634992332820282019728792003956564819967", + "active": true, + "status": "Registered", + "lastRewardRound": { + "id": "2535", + "length": "5760", + "startBlock": "14601600", + "endBlock": "14607360", + "mintableTokens": "6289.390217651615209644", + "volumeETH": "0", + "volumeUSD": "0", + "totalActiveStake": "12660572.689057253001431262", + "totalSupply": "25315641.406774142960762968", + "participationRate": "0.5001087069304688888807674462863896", + "movedStake": "0", + "newStake": "0" + }, + "rewardCut": "2500", + "feeShare": "100000", + "pendingFeeShare": "0", + "pendingRewardCut": "0", + "totalStake": "10359.571442424819689212", + "totalVolumeETH": "0", + "totalVolumeUSD": "0", + "serviceURI": "https://lpt.4v1.in:8935", + "delegators": [ + { + "id": "0x1a196b031ea1a74a53ecbe6148772648e02f9d51", + "bondedAmount": "33.050240717610249021", + "startRound": "2467" + }, + { + "id": "0x683fc3000a300575657713124fcf84adc53f9f90", + "bondedAmount": "11.81774", + "startRound": "2468" + }, + { + "id": "0x9785c9c3258573810c69ddf93221b6a8dea1c777", + "bondedAmount": "0.000000000000000001", + "startRound": "2467" + }, + { + "id": "0xfb9849b0b53f66b747bfa47396964a3fa22400a0", + "bondedAmount": "10071.316871799952124909", + "startRound": "2487" + } + ], + "delegator": { + "id": "0x1a196b031ea1a74a53ecbe6148772648e02f9d51", + "bondedAmount": "33.050240717610249021", + "startRound": "2467" + }, + "lastGet": 1650188936614 +} \ No newline at end of file diff --git a/src/actions/livepeer.js b/src/actions/livepeer.js index 66dbdfd..e2fcb28 100644 --- a/src/actions/livepeer.js +++ b/src/actions/livepeer.js @@ -159,13 +159,13 @@ export const getEvents = () => async dispatch => { tmpAmount.toFixed(2) + " LPT stake", "round " + tmpWhen ] - eventDescription = + eventDescription = } else { const subtext = "reactivated"; const descriptions = [ "round " + tmpWhen ] - eventDescription = + eventDescription = } } // Lone Unbond => Unbond Event @@ -178,7 +178,7 @@ export const getEvents = () => async dispatch => { "round " + tmpWhen ] eventDescription = - + } // Lone Bond => Stake Event else if (eventContainsBond) { @@ -194,7 +194,7 @@ export const getEvents = () => async dispatch => { tmpAmount.toFixed(2) + " LPT" ] eventDescription = - + } // Fill description of Stake Event if it wasn't set yet @@ -205,7 +205,7 @@ export const getEvents = () => async dispatch => { tmpAmount.toFixed(2) + " LPT" ] eventDescription = - + } else if (eventFrom === eventTo) { eventFrom = ""; const subtext = "changed stake"; @@ -213,14 +213,14 @@ export const getEvents = () => async dispatch => { tmpAmount.toFixed(2) + " LPT" ] eventDescription = - + } else { const subtext = "moved stake"; const descriptions = [ tmpAmount.toFixed(2) + " LPT" ] eventDescription = - + } } @@ -277,7 +277,7 @@ export const getEvents = () => async dispatch => { "round " + eventObj.data.withdrawRound ] const txt = - + finalEventList.push({ eventType: "Withdraw", eventDescription: txt, @@ -301,7 +301,7 @@ export const getEvents = () => async dispatch => { amount.toFixed(4) + " Eth" ] const txt = - + finalEventList.push({ eventType: "Withdraw", eventDescription: txt, @@ -327,7 +327,7 @@ export const getEvents = () => async dispatch => { amount2.toFixed(2) + "% on transcoding fees" ] const txt = - + finalEventList.push({ eventType: "Update", eventDescription: txt, @@ -357,7 +357,7 @@ export const getEvents = () => async dispatch => { "+" + amount2.toFixed(4) + " Eth fees" ] let txt = - + finalEventList.push({ eventType: "Claim", eventDescription: txt, @@ -381,7 +381,7 @@ export const getEvents = () => async dispatch => { "+" + amount1.toFixed(2) + " LPT" + (Math.floor(amount1) == 69 ? "... Nice!" : "") ] const txt = - + finalEventList.push({ eventType: "Reward", eventDescription: txt, @@ -483,7 +483,7 @@ export const getTickets = () => async dispatch => { "+" + amount.toFixed(4) + " Eth" ] const txt = - + finalTicketList.push({ eventType: "RedeemTicket", eventDescription: txt, @@ -535,12 +535,21 @@ export const getCurrentOrchestratorInfo = () => async dispatch => { return dispatch(receiveErrors(data)); }; +export const getOrchestratorInfoSilent = (orchAddr) => async dispatch => { + const response = await apiUtil.getOrchestratorInfo(orchAddr); + const data = await response.json(); + if (response.ok) { + if (data && data.id) { + return dispatch(cacheNewOrch(data)); + } + } +}; + export const getOrchestratorInfo = (orchAddr) => async dispatch => { const response = await apiUtil.getOrchestratorInfo(orchAddr); const data = await response.json(); if (response.ok) { if (data && data.id) { - console.log(data); dispatch(cacheNewOrch(data)); return dispatch(setOrchestratorInfo(data)); } else { @@ -598,7 +607,9 @@ export const getAllThreeBoxInfo = () => async dispatch => { export const getThreeBoxInfo = async (addr) => { const response = await apiUtil.getThreeBox(addr); - const data = await response.json(); + if (response.ok) { + const data = await response.json(); + } }; export const getOrchestratorScores = (year, month) => async dispatch => { diff --git a/src/components/TicketViewer.js b/src/components/TicketViewer.js index 9b73110..22e4963 100644 --- a/src/components/TicketViewer.js +++ b/src/components/TicketViewer.js @@ -17,7 +17,7 @@ const Ticket = (obj) => {
{obj.descriptions.map(function (thisTextItem, i) { return ( -

+

{thisTextItem}

) diff --git a/src/components/WinnerMonth.js b/src/components/WinnerMonth.js index 34d1a71..3d56dff 100644 --- a/src/components/WinnerMonth.js +++ b/src/components/WinnerMonth.js @@ -90,10 +90,11 @@ const WinnerMonth = (obj) => { return (
+

Top Earners

{ const dispatch = useDispatch(); const livepeer = useSelector((state) => state.livepeerstate); const [hasRefreshed, setRefresh] = useState(false); + const [hasENS, setHasENS] = useState(false); + const [hasThreeBox, setHasThreeBox] = useState(false); const [hasThreeBoxRefreshed, setThreeBoxRefresh] = useState(false); - let thisDomain = null; - let thisInfo = null; - let hasENS = false; - let hasThreeBox = false; + const [hasOrchInfo, setHasOrchInfo] = useState(false); + const [orchInfo, setOrchInfo] = useState(null); const now = new Date().getTime(); - // Lookup domain in cache - if (livepeer.ensDomainMapping) { - for (const thisAddr of livepeer.ensDomainMapping) { - if (thisAddr.address === obj.address) { - thisDomain = thisAddr; - // Check timeout - if (now - thisAddr.timestamp < 86400000) { - break; - } - // Is outdated - if (!hasRefreshed) { - getEnsInfo(obj.address); - setRefresh(true); - } - break; - } - } - // If it was not cached at all - if (thisDomain == null && !hasRefreshed) { - setRefresh(true); - getEnsInfo(obj.address); - } - } - // 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) { - thisInfo = thisAddr; - hasENS = true; - // Check timeout - if (now - thisAddr.timestamp < 86400000) { - break; - } - // Is outdated - if (!hasRefreshed) { - getEnsInfo(obj.address); - setRefresh(true); - } - break; - } - } - // If it was not cached at all - if (thisInfo == null && !hasRefreshed) { - getEnsInfo(obj.address); - setRefresh(true); - } - } - - // Ugly shit, but temporary for now to quickly enable threebox. Sorry! - if (!hasENS) { - if (livepeer.threeBoxInfo) { - for (const thisAddr of livepeer.threeBoxInfo) { + + useEffect(() => { + let thisInfo = null; + let thisDomain = null; + // Lookup domain in cache + if (livepeer.ensDomainMapping && !hasRefreshed) { + for (const thisAddr of livepeer.ensDomainMapping) { if (thisAddr.address === obj.address) { - thisInfo = thisAddr; - hasThreeBox = true; + thisDomain = thisAddr; // Check timeout if (now - thisAddr.timestamp < 86400000) { break; } // Is outdated - if (!hasThreeBoxRefreshed) { - getThreeBoxInfo(obj.address); - setThreeBoxRefresh(true); + if (!hasRefreshed) { + getEnsInfo(obj.address); + setRefresh(true); } break; } } // If it was not cached at all - if (thisDomain == null && !hasThreeBoxRefreshed) { - setThreeBoxRefresh(true); - getThreeBoxInfo(obj.address); + if (thisDomain == null && !hasRefreshed) { + setRefresh(true); + getEnsInfo(obj.address); } } - } + // Lookup current info in cache only if this addr has a mapped ENS domain + if (thisDomain && thisDomain.domain && !hasRefreshed) { + for (const thisAddr of livepeer.ensInfoMapping) { + if (thisAddr.domain === thisDomain.domain) { + thisInfo = thisAddr; + setHasENS(true); + // Check timeout + if (now - thisAddr.timestamp < 86400000) { + break; + } + // Is outdated + if (!hasRefreshed) { + getEnsInfo(obj.address); + setRefresh(true); + } + break; + } + } + // If it was not cached at all + if (thisInfo == null && !hasRefreshed) { + getEnsInfo(obj.address); + setRefresh(true); + } + } + + // Ugly shit, but temporary for now to quickly enable threebox. Sorry! + if (!hasENS && !hasThreeBoxRefreshed) { + if (livepeer.threeBoxInfo) { + for (const thisAddr of livepeer.threeBoxInfo) { + if (thisAddr.address === obj.address) { + thisInfo = thisAddr; + setHasThreeBox(true); + // Check timeout + if (now - thisAddr.timestamp < 86400000) { + break; + } + // Is outdated + if (!hasThreeBoxRefreshed) { + getThreeBoxInfo(obj.address); + setThreeBoxRefresh(true); + } + break; + } + } + // If it was not cached at all + if (thisDomain == null && !hasThreeBoxRefreshed) { + setThreeBoxRefresh(true); + getThreeBoxInfo(obj.address); + } + } + } + if (thisInfo && thisInfo != orchInfo){ + setOrchInfo(thisInfo); + } + }, [livepeer.ensDomainMapping, livepeer.threeBoxInfo, hasRefreshed, hasENS, hasThreeBoxRefreshed]); + + useEffect(() => { + // Check if cached as an orchestrator + if (livepeer.orchInfo && !hasOrchInfo) { + for (const thisOrch of livepeer.orchInfo) { + if (thisOrch.id === obj.address) { + setHasOrchInfo(true); + break; + } + } + // Preload Orch info + if (!hasOrchInfo) { + dispatch(getOrchestratorInfoSilent(obj.address)); + setHasOrchInfo(true); + } + } + }, [livepeer.orchInfo, hasOrchInfo]); let thisName; let thisIcon; if (hasENS) { - thisName =

{thisInfo.domain}

; - if (thisInfo.avatar) { + thisName =

{orchInfo.domain}

; + if (orchInfo.avatar) { thisIcon = - - + + } } else if (hasThreeBox) { - if (thisInfo.name) { - thisName =

{thisInfo.name}

; + if (orchInfo.name) { + thisName =

{orchInfo.name}

; } else { thisName = {obj.address}; } - if (thisInfo.image) { - thisIcon = + if (orchInfo.image) { + thisIcon = } else { thisIcon = null; } diff --git a/src/pages/tickets.js b/src/pages/tickets.js index cb9de52..b49f173 100644 --- a/src/pages/tickets.js +++ b/src/pages/tickets.js @@ -5,11 +5,13 @@ import { useSelector, useDispatch } from 'react-redux'; import { Accordion } from '@mantine/core'; import ScrollContainer from 'react-indiana-drag-scroll'; import WinnerMonth from '../components/WinnerMonth'; +import { VictoryPie } from 'victory'; const Tickets = (obj) => { const livepeer = useSelector((state) => state.livepeerstate); const [ticketsPerMonth, setTicketsPerMonth] = useState([]); const [redirectToHome, setRedirectToHome] = useState(false); + const [removeOnlyStakers, setRemoveOnlyStakers] = useState(false); console.log("Rendering Winning Ticket Viewer"); @@ -138,6 +140,117 @@ const Tickets = (obj) => { return ; } + const getName = (address) => { + let thisDomain = null; + // Lookup domain in cache + if (livepeer.ensDomainMapping) { + for (const thisAddr of livepeer.ensDomainMapping) { + if (thisAddr.address === address) { + thisDomain = thisAddr; + break; + } + } + } + // Lookup current info in cache only if this addr has a mapped ENS domain + if (thisDomain && thisDomain.domain) { + for (const thisAddr of livepeer.ensInfoMapping) { + if (thisAddr.domain === thisDomain.domain) { + return thisAddr.domain; + } + } + } + + if (livepeer.threeBoxInfo) { + for (const thisAddr of livepeer.threeBoxInfo) { + if (thisAddr.address === address) { + if (thisAddr.name) { + return thisAddr.name; + } else { + return (address.substring(0, 10) + ".."); + } + break; + } + } + } + + return (address.substring(0, 10) + ".."); + } + + let pieList = []; + let otherSum = 0; + let pieObj = null; + if (livepeer.orchInfo) { + let orchIdx = livepeer.orchInfo.length - 1; + // calc sum of stake + let totalStake = 0; + while (orchIdx >= 0) { + const thisOrch = livepeer.orchInfo[orchIdx]; + orchIdx -= 1; + if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) { + continue; + } + totalStake += parseInt(thisOrch.totalStake); + } + // create slices + orchIdx = livepeer.orchInfo.length - 1; + while (orchIdx >= 0) { + const thisOrch = livepeer.orchInfo[orchIdx]; + orchIdx -= 1; + if (removeOnlyStakers && !parseInt(thisOrch.totalVolumeUSD)) { + continue; + } + if ((thisOrch.totalStake / totalStake) < 0.04) { + otherSum += thisOrch.totalStake; + } else { + pieList.push({ + address: getName(thisOrch.id), + sum: thisOrch.totalStake + }); + } + } + pieList.push({ + address: "Other", + sum: otherSum + }); + pieObj =
+

Active Orchestrators by Stake

+
+

Show non-transcoding Orchestrators?

+
setRemoveOnlyStakers(!removeOnlyStakers)}> +
+ {removeOnlyStakers ? "Show" : "Hide"} +
+
+
+ +
+ } + return (