diff --git a/backend/src/models/ClaimEvent.js b/backend/src/models/ClaimEvent.js index bee011e..4bf5409 100644 --- a/backend/src/models/ClaimEvent.js +++ b/backend/src/models/ClaimEvent.js @@ -13,6 +13,14 @@ const ClaimEventSchema = new mongoose.Schema({ type: Number, required: true }, + startRound: { + type: Number, + required: true + }, + endRound: { + type: Number, + required: true + }, transactionHash: { type: String, required: true diff --git a/backend/src/routes/livepeer.js b/backend/src/routes/livepeer.js index fce4bac..2204527 100644 --- a/backend/src/routes/livepeer.js +++ b/backend/src/routes/livepeer.js @@ -172,6 +172,94 @@ let stakeEventCache = []; let monthlyStatCache = []; +apiRouter.get("/getAllMonthlyStats", async (req, res) => { + try { + res.send(monthlyStatCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllUpdateEvents", async (req, res) => { + try { + res.send(updateEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllRewardEvents", async (req, res) => { + try { + res.send(rewardEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllClaimEvents", async (req, res) => { + try { + res.send(claimEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllWithdrawStakeEvents", async (req, res) => { + try { + res.send(withdrawStakeEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllWithdrawFeesEvents", async (req, res) => { + try { + res.send(withdrawFeesEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllTransferTicketEvents", async (req, res) => { + try { + res.send(transferTicketEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllRedeemTicketEvents", async (req, res) => { + try { + res.send(redeemTicketEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllActivateEvents", async (req, res) => { + try { + res.send(activateEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllUnbondEvents", async (req, res) => { + try { + res.send(unbondEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/getAllStakeEvents", async (req, res) => { + try { + res.send(stakeEventCache); + } catch (err) { + res.status(400).send(err); + } +}); + /* SMART CONTRACT EVENTS - MONTHLY STATS UPDATING @@ -712,6 +800,8 @@ const parseAnyEvent = async function (thisEvent) { address: thisEvent.data.delegator.toLowerCase(), fees: parseFloat(thisEvent.data.rewards) / 1000000000000000000, rewards: parseFloat(thisEvent.data.fees) / 1000000000000000000, + startRound: parseInt(thisEvent.data.startRound), + endRound: parseInt(thisEvent.data.endRound), transactionHash: thisEvent.transactionHash, blockNumber: thisEvent.blockNumber, blockTime: thisEvent.blockTime @@ -988,8 +1078,11 @@ const syncEvents = function (toBlock) { console.log("Starting sync process for Bonding Manager events to block " + toBlock); isEventSyncing = true; let lastTxSynced = 0; + if (lastBlockTickets != 'latest'){ + lastBlockTickets += 1; + } // Then do a sync from last found until latest known - bondingManagerContract.getPastEvents("allEvents", { fromBlock: lastBlockEvents + 1, toBlock: toBlock }, async (error, events) => { + bondingManagerContract.getPastEvents("allEvents", { fromBlock: lastBlockEvents, toBlock: toBlock }, async (error, events) => { try { if (error) { throw error @@ -1042,8 +1135,11 @@ const syncEvents = function (toBlock) { const syncTickets = function (toBlock) { console.log("Starting sync process for Ticket Broker events to block " + toBlock); isTicketSyncing = true; + if (lastBlockTickets != 'latest'){ + lastBlockTickets += 1; + } // Then do a sync from last found until latest known - ticketBrokerContract.getPastEvents("allEvents", { fromBlock: lastBlockTickets + 1, toBlock: toBlock }, async (error, events) => { + ticketBrokerContract.getPastEvents("allEvents", { fromBlock: lastBlockTickets, toBlock: toBlock }, async (error, events) => { try { if (error) { throw error diff --git a/src/App.js b/src/App.js index 84d08f6..ae6e686 100644 --- a/src/App.js +++ b/src/App.js @@ -3,7 +3,7 @@ import Home from './pages/home.js'; import Startup from './pages/loadingScreen.js'; import Grafana from './pages/grafana.js'; import Livepeer from './pages/livepeer.js'; -import Tickets from './pages/tickets.js'; +import Stats from './pages/stats.js'; import { BrowserRouter as Router, @@ -17,7 +17,8 @@ export default function App() { } /> - } /> + } /> + } /> } /> } /> diff --git a/src/actions/livepeer.js b/src/actions/livepeer.js index f149a37..c39cb13 100644 --- a/src/actions/livepeer.js +++ b/src/actions/livepeer.js @@ -1,21 +1,5 @@ import * as apiUtil from "../util/livepeer"; import { receiveErrors } from "./error"; -import React from "react"; -import Ticket from "../components/TicketViewer"; - -const claimColour = "rgba(25, 158, 29, 0.3)"; -const stakeColour = "rgba(25, 158, 147, 0.3)"; -const ticketRedeemColour = "rgba(25, 98, 158, 0.3)"; -const rewardColour = "rgba(25, 27, 158, 0.3)"; -const unbondColour = "rgba(105, 25, 158, 0.3)"; -const updateColour = "rgba(158, 25, 52, 0.3)"; -const withdrawStakeColour = "rgba(158, 98, 25, 0.3)"; -const activationColour = "rgba(154, 158, 25, 0.3)"; - -const ticketTransferColour = "rgba(88, 91, 42, 0.3)"; - -const thresholdStaking = 0.001; -const thresholdFees = 0.00009; export const RECEIVE_QUOTES = "RECEIVE_QUOTES"; export const RECEIVE_BLOCKCHAIN_DATA = "RECEIVE_BLOCKCHAIN_DATA"; @@ -32,6 +16,17 @@ export const SET_ALL_THREEBOX_INFO = "SET_ALL_THREEBOX_INFO"; export const SET_ALL_ORCH_SCORES = "SET_ALL_ORCH_SCORES"; export const SET_ALL_ORCH_INFO = "SET_ALL_ORCH_INFO"; export const SET_ALL_DEL_INFO = "SET_ALL_DEL_INFO"; +export const SET_ALL_MONTHLY_STATS = "SET_ALL_MONTHLY_STATS"; +export const SET_ALL_UPDATE_EVENTS = "SET_ALL_UPDATE_EVENTS"; +export const SET_ALL_REWARD_EVENTS = "SET_ALL_REWARD_EVENTS"; +export const SET_ALL_CLAIM_EVENTS = "SET_ALL_CLAIM_EVENTS"; +export const SET_ALL_WITHDRAW_STAKE_EVENTS = "SET_ALL_WITHDRAW_STAKE_EVENTS"; +export const SET_ALL_WITHDRAW_FEES_EVENTS = "SET_ALL_WITHDRAW_FEES_EVENTS"; +export const SET_ALL_TRANSFER_TICKET_EVENTS = "SET_ALL_TRANSFER_TICKET_EVENTS"; +export const SET_ALL_REDEEM_TICKET_EVENTS = "SET_ALL_REDEEM_TICKET_EVENTS"; +export const SET_ALL_ACTIVATE_EVENTS = "SET_ALL_ACTIVATE_EVENTS"; +export const SET_ALL_UNBOND_EVENTS = "SET_ALL_UNBOND_EVENTS"; +export const SET_ALL_STAKE_EVENTS = "SET_ALL_STAKE_EVENTS"; const setQuotes = message => ({ type: RECEIVE_QUOTES, message @@ -80,7 +75,49 @@ const setAllDelInfo = message => ({ type: SET_ALL_DEL_INFO, message }); +const setAllMonthlyStats = message => ({ + type: SET_ALL_MONTHLY_STATS, message +}); +const setAllUpdateEvents = message => ({ + type: SET_ALL_UPDATE_EVENTS, message +}); + +const setAllRewardEvents = message => ({ + type: SET_ALL_REWARD_EVENTS, message +}); + +const setAllClaimEvents = message => ({ + type: SET_ALL_CLAIM_EVENTS, message +}); + +const setAllWithdrawStakeEvents = message => ({ + type: SET_ALL_WITHDRAW_STAKE_EVENTS, message +}); + +const setAllWithdrawFeesEvents = message => ({ + type: SET_ALL_WITHDRAW_FEES_EVENTS, message +}); + +const setAllTransferTicketEvents = message => ({ + type: SET_ALL_TRANSFER_TICKET_EVENTS, message +}); + +const setAllRedeemTicketEvents = message => ({ + type: SET_ALL_REDEEM_TICKET_EVENTS, message +}); + +const setAllActivateEvents = message => ({ + type: SET_ALL_ACTIVATE_EVENTS, message +}); + +const setAllUnbondEvents = message => ({ + type: SET_ALL_UNBOND_EVENTS, message +}); + +const setAllStakeEvents = message => ({ + type: SET_ALL_STAKE_EVENTS, message +}); export const getQuotes = () => async dispatch => { const response = await apiUtil.getQuotes(); @@ -100,426 +137,6 @@ export const getBlockchainData = () => async dispatch => { return dispatch(receiveErrors(data)); }; -export const getEvents = () => async dispatch => { - const response = await apiUtil.getEvents(); - const data = await response.json(); - // Combine raw list of events into a list of useful Events - if (response.ok) { - let finalEventList = []; - // Current transaction we are processing - let txCounter = 0; - let currentTx = ""; - let currentUrl = ""; - let currentBlock = 0; - let currentTime = 0; - // Current Event we are processing - let eventType = ""; // Named type: Withdraw, Update, Claim, Reward, Activate, Unbond, Stake - let eventDescription = ""; // Descriptive text, also containing Amount, AmountOther and When - let eventCaller = ""; // address we will display on the left side - let eventFrom = ""; // address from which X gets taken - let eventTo = ""; // address to which X gets sent - let eventColour = "rgba(255,255,255,0.5)"; - let eventContainsBond = false; - let eventContainsTranscoderActivated = false; - let eventContainsUnbond = false; - let eventContainsRebond = false; - let eventContainsTransferBond = false; - let eventContainsReward = false; - // Temp vars for the current Event we are processing - let tmpAmount = 0; - let tmpAmountOther = ""; - let tmpWhen = ""; - // Group Events into transactions. Always reset when the transactionID changes - { - for (const eventObj of data) { - if (currentTx === "") { - currentTx = eventObj.transactionHash; - currentUrl = eventObj.transactionUrl; - currentBlock = eventObj.blockNumber; - currentTime = eventObj.blockTime; - } - // New transaction found - if (currentTx !== eventObj.transactionHash) { - // Unbond <> TransferBond <> (eventContainsEarningsClaimed) <> Rebond => Stake Event - if (eventContainsUnbond && eventContainsTransferBond && eventContainsRebond) { - eventType = "Stake"; - eventColour = stakeColour; - } - // (Bond <>) TranscoderActivated => Activate Event - else if (eventContainsTranscoderActivated) { - eventType = "Activate"; - eventColour = activationColour; - eventFrom = ""; - eventTo = ""; - if (eventContainsBond) { - const subtext = "activated"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT stake", - "round " + tmpWhen - ] - eventDescription = - } else { - const subtext = "reactivated"; - const descriptions = [ - "round " + tmpWhen - ] - eventDescription = - } - } - // Lone Unbond => Unbond Event - else if (eventContainsUnbond) { - eventType = "Unbond"; - eventColour = unbondColour; - const subtext = "unbonded"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT", - "round " + tmpWhen - ] - eventDescription = - - } - // Lone Bond => Stake Event - else if (eventContainsBond) { - eventType = "Stake"; - eventColour = stakeColour; - } - // Lone Rebond => Stake Event - else if (eventContainsRebond) { - eventType = "Stake"; - eventColour = stakeColour; - const subtext = "changed stake"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT" - ] - eventDescription = - - } - - // Fill description of Stake Event if it wasn't set yet - if (eventType === "Stake" && eventDescription === "") { - if (eventFrom === "0x0000000000000000000000000000000000000000") { - const subtext = "is now staking"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT" - ] - eventDescription = - - } else if (eventFrom === eventTo) { - eventFrom = ""; - const subtext = "changed stake"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT" - ] - eventDescription = - - } else { - const subtext = "moved stake"; - const descriptions = [ - tmpAmount.toFixed(2) + " LPT" - ] - eventDescription = - - - } - } - // If we have an eventType at this point, we have a completed Event from the previous transaction - if (eventType !== "") { - finalEventList.push({ - eventType, - eventDescription, - eventCaller, - eventFrom, - eventTo, - eventColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: (tmpAmount > tmpAmountOther) ? tmpAmount : tmpAmountOther - }); - } - - // Reset event data - eventType = ""; - eventDescription = ""; - eventCaller = ""; - eventFrom = ""; - eventTo = ""; - eventColour = ""; - tmpAmount = 0; - tmpAmountOther = ""; - tmpWhen = ""; - eventContainsBond = false; - eventContainsTranscoderActivated = false; - eventContainsUnbond = false; - eventContainsRebond = false; - eventContainsTransferBond = false; - eventContainsReward = false; - txCounter++; - currentTx = eventObj.transactionHash; - currentUrl = eventObj.transactionUrl; - currentBlock = eventObj.blockNumber; - currentTime = eventObj.blockTime; - } - // Always split off WithdrawStake as a separate Withdraw Event - if (eventObj.name === "WithdrawStake") { - const amount = parseFloat(eventObj.data.amount) / 1000000000000000000; - if (amount < thresholdFees) { - continue; - } - const subtext = "withdrew stake"; - const descriptions = [ - amount.toFixed(2) + " LPT", - "round " + eventObj.data.withdrawRound - ] - const txt = - - finalEventList.push({ - eventType: "Withdraw", - eventDescription: txt, - eventCaller: eventObj.data.delegator.toLowerCase(), - eventFrom: "", - eventTo: "", - eventColour: withdrawStakeColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: amount - }); - } else if (eventObj.name === "WithdrawFees") { - const amount = parseFloat(eventObj.data.amount) / 1000000000000000000; - if (amount < thresholdFees) { - continue; - } - const subtext = "withdrew fees"; - const descriptions = [ - amount.toFixed(4) + " Eth" - ] - const txt = - - finalEventList.push({ - eventType: "Withdraw", - eventDescription: txt, - eventCaller: eventObj.data.delegator.toLowerCase(), - eventFrom: eventObj.data.delegator.toLowerCase(), - eventTo: "", - eventColour: withdrawStakeColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: amount - }); - } - // Always split off TranscoderUpdate as a separate Update Event - else if (eventObj.name === "TranscoderUpdate") { - const amount1 = parseFloat(eventObj.data.rewardCut) / 10000; - const amount2 = 100 - (eventObj.data.feeShare / 10000); - const subtext = "changed commission"; - const descriptions = [ - amount1.toFixed(2) + "% on staking rewards", - amount2.toFixed(2) + "% on transcoding fees" - ] - const txt = - - finalEventList.push({ - eventType: "Update", - eventDescription: txt, - eventCaller: eventObj.data.transcoder.toLowerCase(), - eventFrom: "", - eventTo: "", - eventColour: updateColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: (amount1 > amount2) ? amount1 : amount2 - }); - } - // Always split off EarningsClaimed as a separate Claim Event - else if (eventObj.name === "EarningsClaimed") { - const amount1 = parseFloat(eventObj.data.rewards) / 1000000000000000000; - const amount2 = parseFloat(eventObj.data.fees) / 1000000000000000000; - if (amount1 < thresholdStaking && amount2 < thresholdFees) { - continue; - } - const subtext = "delegator claimed"; - const descriptions = [ - (eventObj.data.endRound - eventObj.data.startRound + 1) + " rounds", - "+" + amount1.toFixed(2) + " LPT rewards", - "+" + amount2.toFixed(4) + " Eth fees" - ] - let txt = - - finalEventList.push({ - eventType: "Claim", - eventDescription: txt, - eventCaller: eventObj.data.delegator.toLowerCase(), - eventFrom: eventObj.data.delegate.toLowerCase(), - eventTo: "", - eventColour: claimColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: (amount1 > amount2) ? amount1 : amount2 - }); - } - // Always split off Reward as a separate Reward Event - else if (eventObj.name === "Reward") { - eventContainsReward = true; - const amount1 = parseFloat(eventObj.data.amount) / 1000000000000000000; - const subtext = "called reward"; - const descriptions = [ - "+" + amount1.toFixed(2) + " LPT" + (Math.floor(amount1) == 69 ? "... Nice!" : "") - ] - const txt = - - finalEventList.push({ - eventType: "Reward", - eventDescription: txt, - eventCaller: eventObj.data.transcoder.toLowerCase(), - eventFrom: "", - eventTo: "", - eventColour: rewardColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: amount1 - }); - } - // Extract useful info from other types of Event - else if (eventObj.name === "Bond") { - eventContainsBond = true; - eventCaller = eventObj.data.delegator.toLowerCase(); - eventFrom = eventObj.data.oldDelegate.toLowerCase(); - eventTo = eventObj.data.newDelegate.toLowerCase(); - tmpAmount = parseFloat(eventObj.data.bondedAmount) / 1000000000000000000; - tmpAmountOther = parseFloat(eventObj.data.additionalAmount) / 1000000000000000000; - } - else if (eventObj.name === "TranscoderActivated") { - eventContainsTranscoderActivated = true; - eventCaller = eventObj.data.transcoder.toLowerCase(); - tmpWhen = eventObj.data.activationRound; - } - else if (eventObj.name === "Unbond") { - eventContainsUnbond = true; - eventCaller = eventObj.data.delegator.toLowerCase(); - eventFrom = eventObj.data.delegate.toLowerCase(); - tmpAmount = parseFloat(eventObj.data.amount) / 1000000000000000000; - tmpWhen = eventObj.data.withdrawRound; - } - else if (eventObj.name === "Rebond") { - eventContainsRebond = true; - eventCaller = eventObj.data.delegator.toLowerCase(); - eventTo = eventObj.data.delegate.toLowerCase(); - tmpAmount = parseFloat(eventObj.data.amount) / 1000000000000000000; - } - else if (eventObj.name === "TransferBond") { - eventContainsTransferBond = true; - if (!eventContainsUnbond) { - eventFrom = eventObj.data.oldDelegator.toLowerCase(); - } - if (!eventContainsRebond) { - eventTo = eventObj.data.newDelegator.toLowerCase(); - } - tmpAmount = parseFloat(eventObj.data.amount) / 1000000000000000000; - } else { - console.log("UNIMPLEMENTED: " + eventObj.name); - } - } - } - // NOTE: We are throwing away the very oldest Event now, which should be fine. - // We can fix this once above wall of text becomes a separate function - return dispatch(setEvents(finalEventList)); - } - return dispatch(receiveErrors(data)); -}; - -export const getTickets = () => async dispatch => { - const response = await apiUtil.getTickets(); - const data = await response.json(); - // Combine raw list of events into a list of useful Events - if (response.ok) { - let finalTicketList = []; - let winningTicketList = []; - // Current transaction we are processing - let txCounter = 0; - let currentTx = ""; - let currentUrl = ""; - let currentBlock = 0; - let currentTime = 0; - // Parse Tickets - { - for (const eventObj of data) { - if (currentTx === "") { - currentTx = eventObj.transactionHash; - currentUrl = eventObj.transactionUrl; - currentBlock = eventObj.blockNumber; - currentTime = eventObj.blockTime; - } - // New transaction found - if (currentTx !== eventObj.transactionHash) { - // Reset event data - txCounter++; - currentTx = eventObj.transactionHash; - currentUrl = eventObj.transactionUrl; - currentBlock = eventObj.blockNumber; - currentTime = eventObj.blockTime; - } - // Always split off WithdrawStake as a separate Withdraw Event - if (eventObj.name === "WinningTicketRedeemed") { - const amount = parseFloat(eventObj.data.faceValue) / 1000000000000000000; - const subtext = "winning ticket"; - const descriptions = [ - "+" + amount.toFixed(4) + " Eth" - ] - const txt = - - finalTicketList.push({ - eventType: "RedeemTicket", - eventDescription: txt, - eventCaller: eventObj.data.recipient.toLowerCase(), - eventFrom: "",//eventObj.data.sender.toLowerCase(), - eventTo: "",//eventObj.data.recipient.toLowerCase(), - eventColour: ticketRedeemColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: amount - }); - } else if (eventObj.name === "WinningTicketTransfer") { - const amount = parseFloat(eventObj.data.amount) / 1000000000000000000; - const txt = " broadcaster payed out " + amount.toFixed(4) + " Eth"; - winningTicketList.push({ - eventType: "TransferTicket", - eventDescription: txt, - eventCaller: "", - eventFrom: eventObj.data.sender.toLowerCase(), - eventTo: eventObj.data.recipient.toLowerCase(), - eventColour: ticketTransferColour, - transactionHash: currentTx, - transactionUrl: currentUrl, - transactionBlock: currentBlock, - transactionTime: currentTime, - eventValue: amount - }); - } else { - console.log("UNIMPLEMENTED: " + eventObj.name); - } - } - } - // NOTE: We are throwing away the very oldest Ticket now, which should be fine. - // We can fix this once above wall of text becomes a separate function - dispatch(setWinningTickets(winningTicketList)); - return dispatch(setTickets(finalTicketList)); - } - return dispatch(receiveErrors(data)); -}; - export const getCurrentOrchestratorInfo = () => async dispatch => { const response = await apiUtil.getCurrentOrchestratorInfo(); const data = await response.json(); @@ -631,4 +248,103 @@ export const getAllDelInfo = () => async dispatch => { return dispatch(setAllDelInfo(data)); } return dispatch(receiveErrors(data)); +}; + +export const getAllMonthlyStats = () => async dispatch => { + const response = await apiUtil.getAllMonthlyStats(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllMonthlyStats(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllUpdateEvents = () => async dispatch => { + const response = await apiUtil.getAllUpdateEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllUpdateEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllRewardEvents = () => async dispatch => { + const response = await apiUtil.getAllRewardEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllRewardEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllClaimEvents = () => async dispatch => { + const response = await apiUtil.getAllClaimEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllClaimEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllWithdrawStakeEvents = () => async dispatch => { + const response = await apiUtil.getAllWithdrawStakeEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllWithdrawStakeEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllWithdrawFeesEvents = () => async dispatch => { + const response = await apiUtil.getAllWithdrawFeesEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllWithdrawFeesEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllTransferTicketEvents = () => async dispatch => { + const response = await apiUtil.getAllTransferTicketEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllTransferTicketEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllRedeemTicketEvents = () => async dispatch => { + const response = await apiUtil.getAllRedeemTicketEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllRedeemTicketEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllActivateEvents = () => async dispatch => { + const response = await apiUtil.getAllActivateEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllActivateEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllUnbondEvents = () => async dispatch => { + const response = await apiUtil.getAllUnbondEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllUnbondEvents(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getAllStakeEvents = () => async dispatch => { + const response = await apiUtil.getAllStakeEvents(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllStakeEvents(data)); + } + return dispatch(receiveErrors(data)); }; \ No newline at end of file diff --git a/src/components/eventButton.js b/src/components/eventButton.js index f8bce9a..5729349 100644 --- a/src/components/eventButton.js +++ b/src/components/eventButton.js @@ -1,13 +1,119 @@ import React from "react"; import Block from "./BlockViewer"; import EventButtonAddress from "./eventButtonAddress"; +import Ticket from "../components/TicketViewer"; + +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)"; /// Displays a single event. Sets selected Orchestrator info in the redux store const EventButton = (obj) => { - let eventTo; - let eventFrom; - let eventCaller; + let eventTo = ""; + let eventFrom = ""; + let eventCaller = ""; + let eventDescription = ""; + let eventColour = greyColour; + + if (obj.type == "update") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = updateColour; + } else if (obj.type == "reward") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = rewardColour; + } else if (obj.type == "claim") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = claimColour; + } else if (obj.type == "withdrawStake") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = withdrawStakeColour; + } else if (obj.type == "withdrawFees") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = withdrawStakeColour; + } else if (obj.type == "activate") { + eventCaller = obj.eventObj.address; + if (obj.eventObj.initialStake) { + eventDescription = + } else { + eventDescription = + } + eventColour = activationColour; + } else if (obj.type == "unbond") { + eventCaller = obj.eventObj.address; + eventFrom = obj.eventObj.from; + eventDescription = + eventColour = unbondColour; + } else if (obj.type == "transferTicket") { + eventCaller = obj.eventObj.address; + eventTo = obj.eventObj.to; + eventDescription = + eventColour = ticketTransferColour; + } else if (obj.type == "redeemTicket") { + eventCaller = obj.eventObj.address; + eventDescription = + eventColour = ticketRedeemColour; + } else if (obj.type == "stake") { + eventCaller = obj.eventObj.address; + eventFrom = obj.eventObj.from; + eventTo = obj.eventObj.to; + if (eventFrom === "0x0000000000000000000000000000000000000000") { + eventFrom = ""; + eventDescription = + } else if (eventFrom === eventTo) { + eventFrom = ""; + eventDescription = + } else { + eventDescription = + } + eventColour = stakeColour; + } + if (obj.eventObj.eventFrom === "0x0000000000000000000000000000000000000000") { obj.eventObj.eventFrom = ""; } @@ -31,21 +137,21 @@ const EventButton = (obj) => { let blockNumber; if (obj.isFirstOfBlock) { - blockNumber = + blockNumber = } return ( -
+
{blockNumber} -
+
{eventCaller}
-
- {obj.eventObj.eventDescription} +
+ {eventDescription}
diff --git a/src/components/eventViewer.js b/src/components/eventViewer.js index e9cf335..227d4bf 100644 --- a/src/components/eventViewer.js +++ b/src/components/eventViewer.js @@ -2,8 +2,9 @@ import React, { useState, useRef } from "react"; import EventButton from "./eventButton"; import ScrollContainer from 'react-indiana-drag-scroll'; import Filter from './filterComponent'; -import ReactPaginate from 'react-paginate'; -/// A scrollable and filterable list of EventButtons + +const thresholdStaking = 0.001; +const thresholdFees = 0.00009; const claimColour = "rgba(25, 158, 29, 0.4)"; const stakeColour = "rgba(25, 158, 147, 0.4)"; @@ -13,6 +14,7 @@ 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 defaultIncrementMaxShown = 50; @@ -65,123 +67,383 @@ const EventViewer = (obj) => { let eventList = []; let thisEvent = {}; - let eventIdx = obj.events.length - 1; - let ticketIdx = obj.tickets.length - 1; - while (eventIdx >= 0 || ticketIdx >= 0) { - const latestEvent = obj.events[eventIdx]; - let latestEventTime = 0; - if (eventIdx >= 0) { - latestEventTime = latestEvent.transactionTime; + let updateEventsIdx = obj.updateEvents.length - 1; + let rewardEventsIdx = obj.rewardEvents.length - 1; + let claimEventsIdx = obj.claimEvents.length - 1; + let withdrawStakeEventsIdx = obj.withdrawStakeEvents.length - 1; + let withdrawFeesEventsIdx = obj.withdrawFeesEvents.length - 1; + let activateEventsIdx = obj.activateEvents.length - 1; + let stakeEventsIdx = obj.stakeEvents.length - 1; + let unbondEventsIdx = obj.unbondEvents.length - 1; + let transferTicketEventsIdx = obj.transferTicketEvents.length - 1; + let redeemTicketEventsIdx = obj.redeemTicketEvents.length - 1; + + if (!filterActivated) { + filtered += activateEventsIdx + 1; + activateEventsIdx = -1; + } + if (!rewardActivated) { + filtered += rewardEventsIdx + 1; + rewardEventsIdx = -1; + } + if (!updateActivated) { + filtered += updateEventsIdx + 1; + updateEventsIdx = -1; + } + if (!withdrawActivated) { + filtered += withdrawStakeEventsIdx + 1; + filtered += withdrawFeesEventsIdx + 1; + withdrawStakeEventsIdx = -1; + withdrawFeesEventsIdx = -1; + } + if (!stakeActivated) { + filtered += stakeEventsIdx + 1; + stakeEventsIdx = -1; + } + if (!unbondActivated) { + filtered += unbondEventsIdx + 1; + unbondEventsIdx = -1; + } + if (!delegatorRewardActivated) { + filtered += rewardEventsIdx + 1; + rewardEventsIdx = -1; + } + if (!rewardActivated) { + filtered += claimEventsIdx + 1; + claimEventsIdx = -1; + } + if (!ticketRedemptionActivated) { + filtered += transferTicketEventsIdx + 1; + filtered += redeemTicketEventsIdx + 1; + transferTicketEventsIdx = -1; + redeemTicketEventsIdx = -1; + } + + + while (updateEventsIdx >= 0 || + rewardEventsIdx >= 0 || + claimEventsIdx >= 0 || + withdrawStakeEventsIdx >= 0 || + withdrawFeesEventsIdx >= 0 || + transferTicketEventsIdx >= 0 || + redeemTicketEventsIdx >= 0 || + activateEventsIdx >= 0 || + unbondEventsIdx >= 0 || + stakeEventsIdx >= 0) { + + let latestTime = 0; + let thisEvent; + let latestType; + + // Find latest event of enabled lists + if (updateEventsIdx >= 0) { + const thisObj = obj.updateEvents[updateEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "update" + } } - const latestTicket = obj.tickets[ticketIdx]; - let latestTicketTime = 0; - if (ticketIdx >= 0) { - latestTicketTime = latestTicket.transactionTime; + if (rewardEventsIdx >= 0) { + const thisObj = obj.rewardEvents[rewardEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "reward" + } } - if (latestEventTime > latestTicketTime) { - thisEvent = latestEvent; - eventIdx -= 1; - } else if (latestTicketTime) { - thisEvent = latestTicket; - ticketIdx -= 1; + if (claimEventsIdx >= 0) { + const thisObj = obj.claimEvents[claimEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "claim" + } + } + if (withdrawStakeEventsIdx >= 0) { + const thisObj = obj.withdrawStakeEvents[withdrawStakeEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "withdrawStake" + } + } + if (withdrawFeesEventsIdx >= 0) { + const thisObj = obj.withdrawFeesEvents[withdrawFeesEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "withdrawFees" + } + } + if (activateEventsIdx >= 0) { + const thisObj = obj.activateEvents[activateEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "activate" + } + } + if (updateEventsIdx >= 0) { + const thisObj = obj.updateEvents[updateEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "update" + } + } + if (stakeEventsIdx >= 0) { + const thisObj = obj.stakeEvents[stakeEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "stake" + } + } + if (unbondEventsIdx >= 0) { + const thisObj = obj.unbondEvents[unbondEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "unbond" + } + } + if (transferTicketEventsIdx >= 0) { + const thisObj = obj.transferTicketEvents[transferTicketEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "transferTicket" + } + } + if (redeemTicketEventsIdx >= 0) { + const thisObj = obj.redeemTicketEvents[redeemTicketEventsIdx]; + if (thisObj.blockTime > latestTime) { + latestTime = thisObj.blockTime; + thisEvent = thisObj; + latestType = "redeemTicket" + } + } + + // Decrement IDX and check filter + if (latestType == "update") { + updateEventsIdx--; + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "reward") { + rewardEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "claim") { + claimEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.fees || + parseFloat(obj.amountFilter) > thisEvent.rewards) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "withdrawStake") { + withdrawStakeEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "withdrawFees") { + withdrawFeesEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "activate") { + activateEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.initialStake) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "update") { + updateEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "stake") { + stakeEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.stake) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (thisEvent.from && thisEvent.from.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (thisEvent.to.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "unbond") { + unbondEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.stake) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (thisEvent.from.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "transferTicket") { + transferTicketEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (thisEvent.to.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } + } else if (latestType == "redeemTicket") { + redeemTicketEventsIdx--; + // Filter by minimum value + if (obj.amountFilter !== "") { + if (parseFloat(obj.amountFilter) > thisEvent.amount) { + filtered++; + continue; + } + } + // Filter name on from, to, caller + if (obj.searchTerm !== "") { + let isFiltered = true; + if (thisEvent.address.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; + if (isFiltered) { + filtered++; + continue; + } + } } else { - console.log("error, breaky breaky"); - break; - } - // Filter by minimum value - if (obj.amountFilter !== "") { - if (parseFloat(obj.amountFilter) > thisEvent.eventValue) { - filtered++; - continue; - } - } - // Filter name on from, to, caller - if (obj.searchTerm !== "") { - let isFiltered = true; - if (thisEvent.eventCaller.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; - if (thisEvent.eventFrom.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; - if (thisEvent.eventTo.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false; - if (isFiltered) { - filtered++; - continue; - } - } - // Filter Events on filter buttons - let isFiltered = true; - // Check boolean filters on thisEvent.eventType - let count = 0; - if (filterActivated) { - if (thisEvent.eventType === "Activate") { - isFiltered = false; - } - count++; - } - if (rewardActivated) { - if (thisEvent.eventType === "Reward") { - isFiltered = false; - } - count++; - } - if (updateActivated) { - if (thisEvent.eventType === "Update") { - isFiltered = false; - } - count++; - } - if (withdrawActivated) { - if (thisEvent.eventType === "Withdraw") { - isFiltered = false; - } - count++; - } - if (stakeActivated) { - if (thisEvent.eventType === "Stake") { - isFiltered = false; - } - count++; - } - if (stakeActivated) { - if (thisEvent.eventType === "Migrate") { - isFiltered = false; - } - count++; - } - if (unbondActivated) { - if (thisEvent.eventType === "Unbond") { - isFiltered = false; - } - count++; - } - if (delegatorRewardActivated) { - if (thisEvent.eventType === "Claim") { - isFiltered = false; - } - count++; - } - if (ticketRedemptionActivated) { - if (thisEvent.eventType === "RedeemTicket") { - isFiltered = false; - } - count++; - } - if (isFiltered && count) { - filtered++; - continue; + console.log("bork"); } + if (unfiltered < obj.maxAmount) { unfiltered++; if (prevBlock === thisEvent.transactionBlock) { eventList.push(); } else { prevBlock = thisEvent.transactionBlock; eventList.push( { return ; } - let eventsList = []; - if (livepeer.events) { - eventsList = livepeer.events; - } - - let ticketList = []; - if (livepeer.tickets) { - ticketList = livepeer.tickets; - } - let thisOrchObj; let headerString; if (livepeer.selectedOrchestrator) { @@ -109,9 +99,20 @@ const Livepeer = (obj) => {
{sidebar}
- + maxAmount={maxAmount} setMaxAmount={setMaxAmount} + updateEvents={livepeer.updateEvents} + rewardEvents={livepeer.rewardEvents} + claimEvents={livepeer.claimEvents} + withdrawStakeEvents={livepeer.withdrawStakeEvents} + withdrawFeesEvents={livepeer.withdrawFeesEvents} + transferTicketEvents={livepeer.transferTicketEvents} + redeemTicketEvents={livepeer.redeemTicketEvents} + activateEvents={livepeer.activateEvents} + unbondEvents={livepeer.unbondEvents} + stakeEvents={livepeer.stakeEvents} + />
diff --git a/src/pages/loadingScreen.js b/src/pages/loadingScreen.js index 34fe98b..a237a78 100644 --- a/src/pages/loadingScreen.js +++ b/src/pages/loadingScreen.js @@ -6,7 +6,7 @@ import { import { getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo, getTickets, getAllEnsDomains, getAllEnsInfo, getAllThreeBoxInfo, getAllOrchScores, getAllOrchInfo, - getAllDelInfo + getAllDelInfo, getAllMonthlyStats } from "../actions/livepeer"; import { login } from "../actions/session"; @@ -23,10 +23,18 @@ const Startup = (obj) => { console.log("Refreshing Livepeer data..."); batch(() => { dispatch(getQuotes()); - dispatch(getEvents()); dispatch(getBlockchainData()); dispatch(getCurrentOrchestratorInfo()); - dispatch(getTickets()); + dispatch(getAllUpdateEvents()); + dispatch(getAllRewardEvents()); + dispatch(getAllClaimEvents()); + dispatch(getAllWithdrawStakeEvents()); + dispatch(getAllWithdrawFeesEvents()); + dispatch(getAllTransferTicketEvents()); + dispatch(getAllRedeemTicketEvents()); + dispatch(getAllActivateEvents()); + dispatch(getAllUnbondEvents()); + dispatch(getAllStakeEvents()); }); } @@ -53,6 +61,7 @@ const Startup = (obj) => { dispatch(getAllOrchInfo()); dispatch(getAllDelInfo()); dispatch(getAllOrchScores()); + dispatch(getAllMonthlyStats()); }); } diff --git a/src/pages/tickets.js b/src/pages/stats.js similarity index 62% rename from src/pages/tickets.js rename to src/pages/stats.js index df23ccd..f3d9ce7 100644 --- a/src/pages/tickets.js +++ b/src/pages/stats.js @@ -6,136 +6,14 @@ import { Accordion } from '@mantine/core'; import ScrollContainer from 'react-indiana-drag-scroll'; import WinnerMonth from '../components/WinnerMonth'; import StakeOverview from '../components/StakeOverview'; -import { VictoryPie } from 'victory'; -const Tickets = (obj) => { +const Stats = (obj) => { const livepeer = useSelector((state) => state.livepeerstate); const [ticketsPerMonth, setTicketsPerMonth] = useState([]); const [redirectToHome, setRedirectToHome] = useState(false); console.log("Rendering Stats Viewer"); - useEffect(() => { - // Process Winning tickets as: - // List of Months containing - // List of Orchestrators (sorted by earnings) containing - // List of winning tickets - let ticketsPerMonth = []; - let ticketIdx = livepeer.winningTickets.length - 1; - let currentMonth = 99; - let currentYear = 99; - let currentOrchCounter = []; - while (ticketIdx >= 0) { - const thisTicket = livepeer.winningTickets[ticketIdx]; - const thisTime = new Date(thisTicket.transactionTime * 1000); - const thisYear = thisTime.getFullYear(); - const thisMonth = thisTime.getMonth(); - ticketIdx -= 1; - - // On a new month - if (thisMonth != currentMonth) { - // Push this months data - if (currentOrchCounter.length) { - // Sort this months data - let sortedList = [] - let currentSum = 0; - while (currentOrchCounter.length) { - let ticketIdx2 = currentOrchCounter.length - 1; - let largestIdx = 0; - let largestValue = 0; - // Find current O with most ticket wins in Eth - while (ticketIdx2 >= 0) { - const currentOrch = currentOrchCounter[ticketIdx2]; - if (currentOrch.sum > largestValue) { - largestIdx = ticketIdx2; - largestValue = currentOrch.sum; - } - ticketIdx2 -= 1; - } - currentSum += largestValue; - // Push current biggest list - sortedList.push(currentOrchCounter[largestIdx]); - // Remove from list - currentOrchCounter.splice(largestIdx, 1); - } - ticketsPerMonth.push( - { - year: currentYear, - month: currentMonth, - orchestrators: sortedList, - total: currentSum - } - ); - } - // clear data - currentMonth = thisMonth; - currentYear = thisYear; - currentOrchCounter = []; - } - // Find orch in list - let thisIdx = 0; - let thisFound = false; - let ticketIdx2 = currentOrchCounter.length - 1; - while (ticketIdx2 >= 0) { - const currentOrch = currentOrchCounter[ticketIdx2]; - if (currentOrch.address == thisTicket.eventTo) { - thisFound = true; - thisIdx = ticketIdx2; - break; - } - ticketIdx2 -= 1; - } - // If not in list, append at the end - if (!thisFound) { - currentOrchCounter.push({ - address: thisTicket.eventTo, - sum: thisTicket.eventValue - }); - } else { - // Else update that entry - currentOrchCounter[thisIdx].sum += thisTicket.eventValue; - } - } - - - if (currentOrchCounter.length) { - // Sort this months data - let sortedList = [] - let currentSum = 0; - while (currentOrchCounter.length) { - let ticketIdx2 = currentOrchCounter.length - 1; - let largestIdx = 0; - let largestValue = 0; - // Find current O with most ticket wins in Eth - while (ticketIdx2 >= 0) { - const currentOrch = currentOrchCounter[ticketIdx2]; - if (currentOrch.sum > largestValue) { - largestIdx = ticketIdx2; - largestValue = currentOrch.sum; - } - ticketIdx2 -= 1; - } - currentSum += largestValue; - // Push current biggest list - sortedList.push(currentOrchCounter[largestIdx]); - // Remove from list - currentOrchCounter.splice(largestIdx, 1); - } - ticketsPerMonth.push( - { - year: currentYear, - month: currentMonth, - orchestrators: sortedList, - total: currentSum - } - ); - } - - - - setTicketsPerMonth(ticketsPerMonth); - }, [livepeer.winningTickets]); - if (redirectToHome) { return ; } @@ -272,4 +150,4 @@ const Tickets = (obj) => { ); } -export default Tickets; \ No newline at end of file +export default Stats; \ No newline at end of file diff --git a/src/reducers/livepeer/livepeerstate.js b/src/reducers/livepeer/livepeerstate.js index f25c911..1baa854 100644 --- a/src/reducers/livepeer/livepeerstate.js +++ b/src/reducers/livepeer/livepeerstate.js @@ -13,20 +13,40 @@ import { SET_ALL_ORCH_SCORES, SET_ALL_ORCH_INFO, SET_ALL_DEL_INFO, - CACHE_ORCHESTRATOR + CACHE_ORCHESTRATOR, + SET_ALL_MONTHLY_STATS, + SET_ALL_UPDATE_EVENTS, + SET_ALL_REWARD_EVENTS, + SET_ALL_CLAIM_EVENTS, + SET_ALL_WITHDRAW_STAKE_EVENTS, + SET_ALL_WITHDRAW_FEES_EVENTS, + SET_ALL_TRANSFER_TICKET_EVENTS, + SET_ALL_REDEEM_TICKET_EVENTS, + SET_ALL_ACTIVATE_EVENTS, + SET_ALL_UNBOND_EVENTS, + SET_ALL_STAKE_EVENTS } from "../../actions/livepeer"; export default (state = { quotes: [], blockchains: [], - events: [], thisOrchestrator: null, selectedOrchestrator: null, - tickets: [], ensInfoMapping: [], ensDomainMapping: [], winningTickets: [], - orchScores: [] + orchScores: [], + monthlyStats: [], + updateEvents: [], + rewardEvents: [], + claimEvents: [], + withdrawStakeEvents: [], + withdrawFeesEvents: [], + transferTicketEvents: [], + redeemTicketEvents: [], + activateEvents: [], + unbondEvents: [], + stakeEvents: [], }, { type, message }) => { Object.freeze(state); switch (type) { @@ -89,6 +109,28 @@ export default (state = { } case SET_ALL_DEL_INFO: return { ...state, delInfo: message }; + case SET_ALL_MONTHLY_STATS: + return { ...state, monthlyStats: message }; + case SET_ALL_UPDATE_EVENTS: + return { ...state, updateEvents: message }; + case SET_ALL_REWARD_EVENTS: + return { ...state, rewardEvents: message }; + case SET_ALL_CLAIM_EVENTS: + return { ...state, claimEvents: message }; + case SET_ALL_WITHDRAW_STAKE_EVENTS: + return { ...state, withdrawStakeEvents: message }; + case SET_ALL_WITHDRAW_FEES_EVENTS: + return { ...state, withdrawFeesEvents: message }; + case SET_ALL_TRANSFER_TICKET_EVENTS: + return { ...state, transferTicketEvents: message }; + case SET_ALL_REDEEM_TICKET_EVENTS: + return { ...state, redeemTicketEvents: message }; + case SET_ALL_ACTIVATE_EVENTS: + return { ...state, activateEvents: message }; + case SET_ALL_UNBOND_EVENTS: + return { ...state, unbondEvents: message }; + case SET_ALL_STAKE_EVENTS: + return { ...state, stakeEvents: message }; default: return { ...state }; } diff --git a/src/util/livepeer.js b/src/util/livepeer.js index ff30298..2e0e3d8 100644 --- a/src/util/livepeer.js +++ b/src/util/livepeer.js @@ -143,4 +143,103 @@ export const getAllDelInfo = () => ( "Content-Type": "application/json" } }) +); + +export const getAllMonthlyStats = () => ( + fetch("api/livepeer/getAllMonthlyStats", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllUpdateEvents = () => ( + fetch("api/livepeer/getAllUpdateEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllRewardEvents = () => ( + fetch("api/livepeer/getAllRewardEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllClaimEvents = () => ( + fetch("api/livepeer/getAllClaimEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllWithdrawStakeEvents = () => ( + fetch("api/livepeer/getAllWithdrawStakeEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllWithdrawFeesEvents = () => ( + fetch("api/livepeer/getAllWithdrawFeesEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllTransferTicketEvents = () => ( + fetch("api/livepeer/getAllTransferTicketEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllRedeemTicketEvents = () => ( + fetch("api/livepeer/getAllRedeemTicketEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllActivateEvents = () => ( + fetch("api/livepeer/getAllActivateEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllUnbondEvents = () => ( + fetch("api/livepeer/getAllUnbondEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllStakeEvents = () => ( + fetch("api/livepeer/getAllStakeEvents", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) ); \ No newline at end of file