From 794e000c4618f32a354391c8df2d72570612540a Mon Sep 17 00:00:00 2001 From: Marco van Dijk Date: Fri, 6 May 2022 17:16:51 +0200 Subject: [PATCH] Added quiet background updates for Events and Monthly stats Fix updating cache of monthly stats correctly Prework on getting round info in order to map Events to Rounds --- backend/src/routes/livepeer.js | 551 +++++++++++++++++++++---- src/actions/livepeer.js | 153 +++++-- src/components/BlockViewer.js | 41 +- src/pages/loadingScreen.js | 69 +++- src/reducers/livepeer/livepeerstate.js | 12 +- src/util/livepeer.js | 99 +++-- 6 files changed, 746 insertions(+), 179 deletions(-) diff --git a/backend/src/routes/livepeer.js b/backend/src/routes/livepeer.js index b39d0dc..26d1ea2 100644 --- a/backend/src/routes/livepeer.js +++ b/backend/src/routes/livepeer.js @@ -41,6 +41,7 @@ const fs = require('fs'); // Used for the livepeer thegraph API import { request, gql } from 'graphql-request'; +import Round from "../models/Round"; // Gets ETH, LPT and other coin info let CoinMarketCap = require('coinmarketcap-api'); @@ -161,24 +162,57 @@ let lastBlockEvents = 0; let lastBlockTickets = 0; let ticketsCache = []; +let alreadyHasAnyRefresh = {}; + let updateEventCache = []; +let alreadyHasUpdateRefresh = {}; + let rewardEventCache = []; +let alreadyHasRewardRefresh = {}; + let claimEventCache = []; +let alreadyHasClaimRefresh = {}; + let withdrawStakeEventCache = []; +let alreadyHasWithdrawStakeRefresh = {}; + let withdrawFeesEventCache = []; +let alreadyHasWithdrawFeesRefresh = {}; + let transferTicketEventCache = []; +let alreadyHasTransferTicketRefresh = {}; + let redeemTicketEventCache = []; +let alreadyHasRedeemTicketRefresh = {}; + let activateEventCache = []; +let alreadyHasActivateRefresh = {}; + let unbondEventCache = []; +let alreadyHasUnbondRefresh = {}; + let stakeEventCache = []; +let alreadyHasStakeRefresh = {}; let monthlyStatCache = []; +let alreadyHasMonthlyStatRefresh = {}; + let commissionDataPointCache = []; let totalStakeDataPoint = []; -apiRouter.get("/getAllMonthlyStats", async (req, res) => { +apiRouter.post("/getAllMonthlyStats", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasMonthlyStatRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(monthlyStatCache); + if (req.session.user.ip) { + alreadyHasMonthlyStatRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } @@ -200,81 +234,209 @@ apiRouter.get("/getAllTotalStakes", async (req, res) => { } }); -apiRouter.get("/getAllUpdateEvents", async (req, res) => { +apiRouter.post("/getAllUpdateEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasUpdateRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(updateEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasUpdateRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllRewardEvents", async (req, res) => { +apiRouter.post("/getAllRewardEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasRewardRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(rewardEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasRewardRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllClaimEvents", async (req, res) => { +apiRouter.post("/getAllClaimEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasClaimRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(claimEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasClaimRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllWithdrawStakeEvents", async (req, res) => { +apiRouter.post("/getAllWithdrawStakeEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasWithdrawStakeRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(withdrawStakeEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasWithdrawStakeRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllWithdrawFeesEvents", async (req, res) => { +apiRouter.post("/getAllWithdrawFeesEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasWithdrawFeesRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(withdrawFeesEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasWithdrawFeesRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllTransferTicketEvents", async (req, res) => { +apiRouter.post("/getAllTransferTicketEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasTransferTicketRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(transferTicketEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasTransferTicketRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllRedeemTicketEvents", async (req, res) => { +apiRouter.post("/getAllRedeemTicketEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasRedeemTicketRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(redeemTicketEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasRedeemTicketRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllActivateEvents", async (req, res) => { +apiRouter.post("/getAllActivateEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasActivateRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(activateEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasActivateRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllUnbondEvents", async (req, res) => { +apiRouter.post("/getAllUnbondEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasUnbondRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(unbondEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasUnbondRefresh[req.session.user.ip] = true; + } } catch (err) { res.status(400).send(err); } }); -apiRouter.get("/getAllStakeEvents", async (req, res) => { +apiRouter.post("/getAllStakeEvents", async (req, res) => { try { + const { smartUpdate } = req.body; + if (smartUpdate && req.session.user.ip) { + if (alreadyHasStakeRefresh[req.session.user.ip]) { + res.send({ noop: true }); + return; + } + } res.send(stakeEventCache); + if (req.session.user.ip) { + alreadyHasAnyRefresh[req.session.user.ip] = true; + alreadyHasStakeRefresh[req.session.user.ip] = true; + } + } catch (err) { + res.status(400).send(err); + } +}); + +apiRouter.get("/hasAnyRefresh", async (req, res) => { + try { + if (req.session.user.ip) { + console.log(req.session.user.ip + " is checking for new Events"); + if (alreadyHasAnyRefresh[req.session.user.ip]) { + console.log(req.session.user.ip + " is still up to date"); + res.send({ requiresRefresh: false }); + return; + } else { + console.log(req.session.user.ip + " requires an update"); + } + } + res.send({ requiresRefresh: true }); } catch (err) { res.status(400).send(err); } @@ -310,13 +472,22 @@ const updateMonthlyReward = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].rewardCount += 1; monthlyStatCache[idx].rewardAmountSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyClaim = async function (blockTime, fees, rewards) { @@ -344,14 +515,23 @@ const updateMonthlyClaim = async function (blockTime, fees, rewards) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].claimCount += 1; monthlyStatCache[idx].claimRewardSum += rewards; monthlyStatCache[idx].claimFeeSum += fees; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyWithdrawStake = async function (blockTime, amount) { @@ -378,13 +558,22 @@ const updateMonthlyWithdrawStake = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].withdrawStakeCount += 1; monthlyStatCache[idx].withdrawStakeAmountSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyWithdrawFees = async function (blockTime, amount) { @@ -411,13 +600,22 @@ const updateMonthlyWithdrawFees = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].withdrawFeesCount += 1; monthlyStatCache[idx].withdrawFeesAmountSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyNewDelegator = async function (blockTime, amount) { @@ -444,13 +642,22 @@ const updateMonthlyNewDelegator = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].bondCount += 1; monthlyStatCache[idx].bondStakeSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyUnbond = async function (blockTime, amount) { @@ -477,13 +684,22 @@ const updateMonthlyUnbond = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].unbondCount += 1; monthlyStatCache[idx].unbondStakeSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyReactivated = async function (blockTime, amount) { @@ -509,12 +725,21 @@ const updateMonthlyReactivated = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].reactivationCount += 1; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyActivation = async function (blockTime, amount) { @@ -541,13 +766,22 @@ const updateMonthlyActivation = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].activationCount += 1; monthlyStatCache[idx].activationInitialSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyMoveStake = async function (blockTime, amount) { @@ -574,13 +808,22 @@ const updateMonthlyMoveStake = async function (blockTime, amount) { }); } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].moveStakeCount += 1; monthlyStatCache[idx].moveStakeSum += amount; + found = true; break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyTicketReceived = async function (blockTime, amount, from, to) { @@ -619,6 +862,8 @@ const updateMonthlyTicketReceived = async function (blockTime, amount, from, to) 'winningTicketsReceived.$.sum': amount + eventObj.sum, 'winningTicketsReceived.$.count': 1 + eventObj.count, } + }, { + new: true }); hasModified = true; break; @@ -638,6 +883,8 @@ const updateMonthlyTicketReceived = async function (blockTime, amount, from, to) count: 1 } } + }, { + new: true }); } // Check to see if the doc's embedded winningTicketsSent already contains this address @@ -654,6 +901,8 @@ const updateMonthlyTicketReceived = async function (blockTime, amount, from, to) 'winningTicketsSent.$.sum': amount + eventObj.sum, 'winningTicketsSent.$.count': 1 + eventObj.count, } + }, { + new: true }); hasModified = true; break; @@ -673,32 +922,62 @@ const updateMonthlyTicketReceived = async function (blockTime, amount, from, to) count: 1 } } + }, { + new: true }); } } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].winningTicketsReceivedCount += 1; monthlyStatCache[idx].winningTicketsReceivedSum += amount; + let foundNested = false; // Check to see if the doc's embedded winningTicketsReceived already contains this address for (var idx2 = 0; idx2 < monthlyStatCache[idx].winningTicketsReceived.length; idx2++) { if (monthlyStatCache[idx].winningTicketsReceived[idx2].address == to) { monthlyStatCache[idx].winningTicketsReceived[idx2].count += 1; monthlyStatCache[idx].winningTicketsReceived[idx2].sum += amount; + foundNested = true; break; } } + if (!foundNested) { + monthlyStatCache[idx].winningTicketsReceived.push({ + address: to, + sum: amount, + count: 1 + }); + } + foundNested = false; // Check to see if the doc's embedded winningTicketsSent already contains this address for (var idx2 = 0; idx2 < monthlyStatCache[idx].winningTicketsSent.length; idx2++) { if (monthlyStatCache[idx].winningTicketsSent[idx2].address == from) { monthlyStatCache[idx].winningTicketsSent[idx2].count += 1; monthlyStatCache[idx].winningTicketsSent[idx2].sum += amount; + foundNested = true; break; } } + if (!foundNested) { + monthlyStatCache[idx].winningTicketsSent.push({ + address: from, + sum: amount, + count: 1 + }); + } + found = true; + break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } const updateMonthlyTicketRedeemed = async function (blockTime, amount, address) { @@ -737,6 +1016,8 @@ const updateMonthlyTicketRedeemed = async function (blockTime, amount, address) 'winningTicketsRedeemed.$.sum': amount + eventObj.sum, 'winningTicketsRedeemed.$.count': 1 + eventObj.count, } + }, { + new: true }); hasModified = true; break; @@ -756,24 +1037,45 @@ const updateMonthlyTicketRedeemed = async function (blockTime, amount, address) count: 1 } } + }, { + new: true }); } } // Update cached entry if it is cached + let found = false; for (var idx = 0; idx < monthlyStatCache.length; idx++) { if (monthlyStatCache[idx].year == thisYear && monthlyStatCache[idx].month == thisMonth) { monthlyStatCache[idx].winningTicketsRedeemedCount += 1; monthlyStatCache[idx].winningTicketsRedeemedSum += amount; + let foundNested = false; // Check to see if the doc's embedded winningTicketsRedeemed already contains this address for (var idx2 = 0; idx2 < monthlyStatCache[idx].winningTicketsRedeemed.length; idx2++) { if (monthlyStatCache[idx].winningTicketsRedeemed[idx2].address == address) { monthlyStatCache[idx].winningTicketsRedeemed[idx2].count += 1; monthlyStatCache[idx].winningTicketsRedeemed[idx2].sum += amount; + foundNested = true; break; } } + if (!foundNested) { + monthlyStatCache[idx].winningTicketsRedeemed.push({ + address: address, + sum: amount, + count: 1 + }); + } + found = true; + break; } } + if (!found) { + const doc = await MonthlyStat.findOne({ + year: thisYear, + month: thisMonth + }); + monthlyStatCache.push(doc); + } } /* @@ -801,6 +1103,8 @@ const parseAnyEvent = async function (thisEvent) { } // No monthly stats updateEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasUpdateRefresh = {}; } else if (thisName === "Reward") { const eventObj = { address: thisEvent.data.transcoder.toLowerCase(), @@ -814,7 +1118,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyReward(eventObj.blockTime, eventObj.amount); + alreadyHasMonthlyStatRefresh = {}; rewardEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasRewardRefresh = {}; } else if (thisName === "EarningsClaimed") { const eventObj = { address: thisEvent.data.delegator.toLowerCase(), @@ -831,7 +1138,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyClaim(eventObj.blockTime, eventObj.fees, eventObj.rewards); + alreadyHasMonthlyStatRefresh = {}; claimEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasClaimRefresh = {}; } else if (thisName === "WithdrawStake") { const eventObj = { address: thisEvent.data.delegator.toLowerCase(), @@ -846,7 +1156,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyWithdrawStake(eventObj.blockTime, eventObj.amount); + alreadyHasMonthlyStatRefresh = {}; withdrawStakeEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasWithdrawStakeRefresh = {}; } else if (thisName === "WithdrawFees") { const eventObj = { address: thisEvent.data.delegator.toLowerCase(), @@ -860,7 +1173,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyWithdrawFees(eventObj.blockTime, eventObj.amount); + alreadyHasMonthlyStatRefresh = {}; withdrawFeesEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasWithdrawFeesRefresh = {}; } else if (thisName === "WinningTicketTransfer") { const eventObj = { address: thisEvent.data.sender.toLowerCase(), @@ -875,7 +1191,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyTicketReceived(eventObj.blockTime, eventObj.amount, eventObj.address, eventObj.to); + alreadyHasMonthlyStatRefresh = {}; transferTicketEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasTransferTicketRefresh = {}; } else if (thisName === "WinningTicketRedeemed") { const eventObj = { address: thisEvent.data.recipient.toLowerCase(), @@ -889,7 +1208,10 @@ const parseAnyEvent = async function (thisEvent) { await dbObj.save(); } updateMonthlyTicketRedeemed(eventObj.blockTime, eventObj.amount, eventObj.address); + alreadyHasMonthlyStatRefresh = {}; redeemTicketEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasRedeemTicketRefresh = {}; } else { console.log("Skipping unknown event of type " + thisName); } @@ -981,7 +1303,10 @@ const parseSequenceEvent = async function () { await dbObj.save(); } updateMonthlyMoveStake(eventObj.blockTime, eventObj.stake); + alreadyHasMonthlyStatRefresh = {}; stakeEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasStakeRefresh = {}; } else if (eventContainsBond && eventContainsTranscoderActivated) { console.log('Parsing TranscoderActivated sequence event'); // Bond -> TranscoderActivated: activation in Round # @@ -998,7 +1323,10 @@ const parseSequenceEvent = async function () { await dbObj.save(); } updateMonthlyActivation(eventObj.blockTime, eventObj.initialStake); + alreadyHasMonthlyStatRefresh = {}; activateEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasActivateRefresh = {}; } else if (eventContainsTranscoderActivated) { console.log('Parsing lone TranscoderActivated sequence event'); // Lone TranscoderActivated: reactivation @@ -1014,7 +1342,10 @@ const parseSequenceEvent = async function () { await dbObj.save(); } updateMonthlyReactivated(eventObj.blockTime); + alreadyHasMonthlyStatRefresh = {}; activateEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasActivateRefresh = {}; } else if (eventContainsUnbond) { console.log('Parsing lone unbond sequence event'); // Lone Unbond: delegator unstaked @@ -1032,7 +1363,10 @@ const parseSequenceEvent = async function () { await dbObj.save(); } updateMonthlyUnbond(eventObj.blockTime, eventObj.stake); + alreadyHasMonthlyStatRefresh = {}; unbondEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasUnbondRefresh = {}; } else if (eventContainsBond) { console.log('Parsing lone bond sequence event'); // Lone Bond: new delegator (Stake event) @@ -1050,7 +1384,10 @@ const parseSequenceEvent = async function () { await dbObj.save(); } updateMonthlyNewDelegator(eventObj.blockTime, eventObj.stake); + alreadyHasMonthlyStatRefresh = {}; stakeEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasStakeRefresh = {}; } else if (eventContainsRebond) { console.log('Parsing lone rebond sequence event'); // Lone Rebond: delegator increased their stake (Stake event) @@ -1068,6 +1405,8 @@ const parseSequenceEvent = async function () { // No monthly stats } stakeEventCache.push(eventObj); + alreadyHasAnyRefresh = {}; + alreadyHasStakeRefresh = {}; } else { console.log('Skipping unknown sequence event'); } @@ -1087,6 +1426,109 @@ const onNewEvent = async function (thisEvent) { } } +/* + +BLOCKS - LIVEPEER ROUNDS +Gets livepeer round number for a given block number +Gets entire round details if the round does not exist yet +Saves entire round details as separate data point as well +Mutates roundCache to contain the new round +Mutates the Event in the database to contain the round number + +*/ + +let roundCache = []; + +const getRoundInfo = async function (blockNumber) { + // Get round info from gql + const roundQuery = gql`{ + rounds(where: {startBlock_lte: "${blockNumber}"}) { + id + length + startBlock + endBlock + mintableTokens + volumeETH + volumeUSD + totalActiveStake + totalSupply + participationRate + movedStake + newStake + } + } + `; + const roundObj = await request("https://api.thegraph.com/subgraphs/name/livepeer/arbitrum-one", roundQuery); + // Not found + if (!roundObj) { + console.log("No round found at block " + blockNumber); + return {}; + } + console.log("This functions is not implemented yet. Logging element to console...") + console.log(roundObj); + // TODO filter out down to 1 round + return roundObj; + // Update cache + roundCache.push(roundObj); + // Only save if the endBlock is elapsed + if (latestBlockInChain > roundObj.endBlock) { + const data = { + number: roundObj.number, + lengthBlocks: roundObj.lengthBlocks, + startBlock: roundObj.startBlock, + endBlock: roundObj.endBlock, + mintableTokens: roundObj.mintableTokens, + volumeEth: roundObj.volumeEth, + volumeUsd: roundObj.volumeUsd, + totalActiveStake: roundObj.totalActiveStake, + totalSupply: roundObj.totalSupply, + participationRate: roundObj.participationRate, + movedStake: roundObj.movedStake, + newStake: roundObj.newStake + } + if (!CONF_DISABLE_DB) { + // TODO only create if nonexistent (find and update with upsert or something) + const dbObj = new Round(data); + await dbObj.save(); + } + } + +} + +apiRouter.post("/getRoundAtBlock", async (req, res) => { + try { + const { blockNumber } = req.body; + if (blockNumber) { + console.log("Getting round info for block " + blockNumber); + // See if it is cached + for (const thisRound of roundCache) { + if (thisRound.startBlock <= blockNumber && thisRound.endBlock >= blockNumber) { + res.send(thisRound); + return; + } + } + // Get block info from thegraph + console.log("Getting round info for block " + blockNumber); + const thisRoundInfo = await getRoundInfo(blockNumber); + res.send(thisRoundInfo); + return; + } + } catch (err) { + console.log(err); + res.status(400).send(err); + } +}); +// Returns entire orch score mapping cache +apiRouter.get("/getAllRounds", async (req, res) => { + try { + res.send(roundCache); + } catch (err) { + res.status(400).send(err); + } +}); + + + /* SMART CONTRACT EVENTS - SYNC BLOCKS @@ -1418,6 +1860,22 @@ const initSync = async function () { timestamp: 1, _id: 0 }); + // Get all round info + roundCache = await Round.find({}, { + number: 1, + lengthBlocks: 1, + startBlock: 1, + endBlock: 1, + mintableTokens: 1, + volumeEth: 1, + volumeUsd: 1, + totalActiveStake: 1, + totalSupply: 1, + participationRate: 1, + movedStake: 1, + newStake: 1, + _id: 0 + }) } let cycle = 0; @@ -1467,8 +1925,8 @@ const handleSync = async function () { // Then loop until we have reached the last known block while (isEventSyncing || isTicketSyncing || !getFinalTickets || !getFinalEvents) { await sleep(500); - if (hasError){ - throw("Error while syncing"); + if (hasError) { + throw ("Error while syncing"); } if (isEventSyncing) { console.log("Parsed " + lastBlockEvents + " out of " + latestBlockInChain + " blocks for Event sync"); @@ -1847,6 +2305,9 @@ const mutateDynamicStatsFromDB = async function (orchestratorObj) { latestCommission: 1, latestTotalStake: 1 }); + if (!doc){ + return; + } let oldFeeCommission = -1; let oldRewardCommission = -1; let oldTotalStake = -1; @@ -2607,69 +3068,5 @@ apiRouter.get("/getAllOrchScores", async (req, res) => { } }); -/* - -BLOCKS - LIVEPEER ROUNDS -Gets livepeer round number for a given block number -Gets entire round details if the round does not exist yet -Saves entire round details as separate data point as well -Mutates roundCache to contain the new round -Mutates the Event in the database to contain the round number - -*/ - -let roundCache = []; -let highestEndblockSeen = 0; - -const mutateRound = async function (scoreObj) { - // Immediately mutate new object - const doc = await MonthlyStat.findOneAndUpdate({ - year: year, - month: month - }, { - testScores: scoreObj - }, { - upsert: true, - new: true, - setDefaultsOnInsert: true - }); k - // Then find and mutate all Event objects which fall in this round -} - -apiRouter.post("/getRoundAtBlock", async (req, res) => { - try { - const { blockNumber } = req.body; - if (blockNumber) { - // See if it is cached - for (const thisRound of roundCache) { - if (thisRound.startBlock <= blockNumber && thisRound.endBlock >= blockNumber) { - if (thisRound.endBlock > highestEndblockSeen) { - - } - res.send(thisAddr); - } - } - // Check DB - // If exists, mutate cache and return value - // Get from thegraph - console.log("Getting new Orchestrator scores for " + year + "-" + month + " @ " + url); - // Save to DB - mutateRound(); - } - } catch (err) { - console.log(err); - res.status(400).send(err); - } -}); -// Returns entire orch score mapping cache -apiRouter.get("/getAllRounds", async (req, res) => { - try { - res.send(roundCache); - } catch (err) { - res.status(400).send(err); - } -}); - - export default apiRouter; \ No newline at end of file diff --git a/src/actions/livepeer.js b/src/actions/livepeer.js index 156ecdc..ebc9bb7 100644 --- a/src/actions/livepeer.js +++ b/src/actions/livepeer.js @@ -28,6 +28,8 @@ 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"; +export const SET_ALL_ROUNDS = "SET_ALL_ROUNDS"; +export const SET_ADD_ROUNDS = "SET_ADD_ROUNDS"; const setQuotes = message => ({ type: RECEIVE_QUOTES, message @@ -125,6 +127,14 @@ const setAllStakeEvents = message => ({ type: SET_ALL_STAKE_EVENTS, message }); +const setAllRounds = message => ({ + type: SET_ALL_ROUNDS, message +}); + +const setAddRound = message => ({ + type: SET_ADD_ROUNDS, message +}); + export const getQuotes = () => async dispatch => { const response = await apiUtil.getQuotes(); const data = await response.json(); @@ -240,11 +250,13 @@ export const getAllDelInfo = () => async dispatch => { return dispatch(receiveErrors(data)); }; -export const getAllMonthlyStats = () => async dispatch => { - const response = await apiUtil.getAllMonthlyStats(); +export const getAllMonthlyStats = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllMonthlyStats(smartUpdate); const data = await response.json(); if (response.ok) { - return dispatch(setAllMonthlyStats(data)); + if (!data.noop) { + return dispatch(setAllMonthlyStats(data)); + } } return dispatch(receiveErrors(data)); }; @@ -267,112 +279,165 @@ export const getAllTotalStakes = () => async dispatch => { return dispatch(receiveErrors(data)); }; -export const getAllUpdateEvents = () => async dispatch => { - const response = await apiUtil.getAllUpdateEvents(); +export const hasAnyRefresh = async () => { + const response = await apiUtil.hasAnyRefresh(); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllUpdateEvents(data)); + if (data) { + if (data.requiresRefresh) { + return true; + } else { + return false; + } + } + } + return true; +}; + + +export const getAllUpdateEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllUpdateEvents(smartUpdate); + const data = await response.json(); + if (response.ok) { + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllUpdateEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllRewardEvents = () => async dispatch => { - const response = await apiUtil.getAllRewardEvents(); +export const getAllRewardEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllRewardEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllRewardEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllRewardEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllClaimEvents = () => async dispatch => { - const response = await apiUtil.getAllClaimEvents(); +export const getAllClaimEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllClaimEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllClaimEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllClaimEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllWithdrawStakeEvents = () => async dispatch => { - const response = await apiUtil.getAllWithdrawStakeEvents(); +export const getAllWithdrawStakeEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllWithdrawStakeEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllWithdrawStakeEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllWithdrawStakeEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllWithdrawFeesEvents = () => async dispatch => { - const response = await apiUtil.getAllWithdrawFeesEvents(); +export const getAllWithdrawFeesEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllWithdrawFeesEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllWithdrawFeesEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllWithdrawFeesEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllTransferTicketEvents = () => async dispatch => { - const response = await apiUtil.getAllTransferTicketEvents(); +export const getAllTransferTicketEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllTransferTicketEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllTransferTicketEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllTransferTicketEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllRedeemTicketEvents = () => async dispatch => { - const response = await apiUtil.getAllRedeemTicketEvents(); +export const getAllRedeemTicketEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllRedeemTicketEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllRedeemTicketEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllRedeemTicketEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllActivateEvents = () => async dispatch => { - const response = await apiUtil.getAllActivateEvents(); +export const getAllActivateEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllActivateEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllActivateEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllActivateEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllUnbondEvents = () => async dispatch => { - const response = await apiUtil.getAllUnbondEvents(); +export const getAllUnbondEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllUnbondEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllUnbondEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllUnbondEvents(data)); + } } } return dispatch(receiveErrors(data)); }; -export const getAllStakeEvents = () => async dispatch => { - const response = await apiUtil.getAllStakeEvents(); +export const getAllStakeEvents = (smartUpdate) => async dispatch => { + const response = await apiUtil.getAllStakeEvents(smartUpdate); const data = await response.json(); if (response.ok) { - if (data && data.length){ - return dispatch(setAllStakeEvents(data)); + if (data && data.length) { + if (!data.noop) { + return dispatch(setAllStakeEvents(data)); + } } } return dispatch(receiveErrors(data)); -}; \ No newline at end of file +}; + +export const getAllRounds = () => async dispatch => { + const response = await apiUtil.getAllRounds(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllRounds(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getRoundAtBlock = (addr) => async dispatch => { + const response = await apiUtil.getRoundAtBlock(addr); + const data = await response.json(); + if (response.ok) { + return dispatch(setAddRound(data)); + } +}; diff --git a/src/components/BlockViewer.js b/src/components/BlockViewer.js index 159e2ff..cc1ee6c 100644 --- a/src/components/BlockViewer.js +++ b/src/components/BlockViewer.js @@ -1,11 +1,49 @@ -import React from 'react'; +import React, { useEffect, useState } from "react"; +import { + getRoundAtBlock +} from "../actions/livepeer"; +import { useDispatch, useSelector } from 'react-redux'; const Block = (obj) => { + const dispatch = useDispatch(); + const livepeer = useSelector((state) => state.livepeerstate); + const [roundInfo, setRoundInfo] = useState(null); + const [hasRefreshed, setRefresh] = useState(false); + + // useEffect(() => { + // let thisInfo = null; + // for (const round of livepeer.rounds) { + // if (round.startBlock <= obj.block && round.endBlock >= obj.block) { + // thisInfo = round; + // break; + // } + // } + // // If it was not cached at all + // if (thisInfo == null && !hasRefreshed) { + // console.log("Refresh due to non-existing round containing this block"); + // setRefresh(true); + // dispatch(getRoundAtBlock(obj.block)); + // } + // if (thisInfo && thisInfo != roundInfo) { + // console.log("Setting block info obj"); + // setRoundInfo(thisInfo); + // } + // }, [livepeer.rounds]); + const thisEpoch = obj.time; var dateObj = new Date(0); dateObj.setUTCSeconds(thisEpoch); const thisLocalDate = dateObj.toLocaleString(); const thisOffset = (-dateObj.getTimezoneOffset() / 60); + + // Get round info + let thisRoundInfo; + if (roundInfo) { + thisRoundInfo =

+ Round {thisRoundInfo.number} +

+ } + return (
@@ -14,6 +52,7 @@ const Block = (obj) => {

🔗

+ {thisRoundInfo}

📅 {thisLocalDate} diff --git a/src/pages/loadingScreen.js b/src/pages/loadingScreen.js index 8004f4b..8aae121 100644 --- a/src/pages/loadingScreen.js +++ b/src/pages/loadingScreen.js @@ -5,11 +5,12 @@ import { } from "../actions/user"; import { getQuotes, getBlockchainData, getCurrentOrchestratorInfo, - getAllEnsDomains, getAllEnsInfo, getAllOrchScores, getAllOrchInfo, + getAllEnsDomains, getAllEnsInfo, getAllOrchScores, getAllOrchInfo, getAllDelInfo, getAllMonthlyStats, getAllUpdateEvents, getAllRewardEvents, getAllClaimEvents, getAllWithdrawStakeEvents, getAllWithdrawFeesEvents, getAllTransferTicketEvents, getAllRedeemTicketEvents, getAllActivateEvents, - getAllUnbondEvents, getAllStakeEvents, getAllCommissions, getAllTotalStakes + getAllUnbondEvents, getAllStakeEvents, getAllCommissions, getAllTotalStakes, + hasAnyRefresh } from "../actions/livepeer"; import { login } from "../actions/session"; @@ -18,6 +19,9 @@ import { login } from "../actions/session"; // Refresh every 60 seconds const refreshInterval = 60000; +// Refresh Events every 10 seconds +const refreshEventsInterval = 10000; + const Startup = (obj) => { const [isLoaded, setIsLoaded] = useState(false); const dispatch = useDispatch(); @@ -30,7 +34,28 @@ const Startup = (obj) => { dispatch(getCurrentOrchestratorInfo()); }); } - + + const refreshEvents = async () => { + console.log("Checking for Events update..."); + const requiresRefresh = await hasAnyRefresh(); + if (requiresRefresh) { + console.log("Events requires update..."); + batch(() => { + dispatch(getAllMonthlyStats(true)); + dispatch(getAllUpdateEvents(true)); + dispatch(getAllRewardEvents(true)); + dispatch(getAllClaimEvents(true)); + dispatch(getAllWithdrawStakeEvents(true)); + dispatch(getAllWithdrawFeesEvents(true)); + dispatch(getAllTransferTicketEvents(true)); + dispatch(getAllRedeemTicketEvents(true)); + dispatch(getAllActivateEvents(true)); + dispatch(getAllUnbondEvents(true)); + dispatch(getAllStakeEvents(true)); + }); + } + } + const refreshLogin = () => { console.log("Logging in and getting visitor statistics..."); batch(() => { @@ -46,41 +71,51 @@ const Startup = (obj) => { dispatch(getAllEnsInfo()); }); } - + const refreshStaticProps = () => { console.log("Refreshing global data..."); batch(() => { dispatch(getAllOrchInfo()); dispatch(getAllDelInfo()); dispatch(getAllOrchScores()); - dispatch(getAllMonthlyStats()); + dispatch(getAllMonthlyStats(false)); dispatch(getAllCommissions()); dispatch(getAllTotalStakes()); - dispatch(getAllUpdateEvents()); - dispatch(getAllRewardEvents()); - dispatch(getAllClaimEvents()); - dispatch(getAllWithdrawStakeEvents()); - dispatch(getAllWithdrawFeesEvents()); - dispatch(getAllTransferTicketEvents()); - dispatch(getAllRedeemTicketEvents()); - dispatch(getAllActivateEvents()); - dispatch(getAllUnbondEvents()); - dispatch(getAllStakeEvents()); + dispatch(getAllUpdateEvents(false)); + dispatch(getAllRewardEvents(false)); + dispatch(getAllClaimEvents(false)); + dispatch(getAllWithdrawStakeEvents(false)); + dispatch(getAllWithdrawFeesEvents(false)); + dispatch(getAllTransferTicketEvents(false)); + dispatch(getAllRedeemTicketEvents(false)); + dispatch(getAllActivateEvents(false)); + dispatch(getAllUnbondEvents(false)); + dispatch(getAllStakeEvents(false)); }); } - + useEffect(() => { refreshLogin(); refreshAllZeData(); refreshENS(); refreshStaticProps(); setIsLoaded(true); + }, []); + + useEffect(() => { if (refreshInterval) { const interval = setInterval(refreshAllZeData, refreshInterval); return () => clearInterval(interval); } }, [refreshInterval]); + useEffect(() => { + if (refreshEventsInterval) { + const intervalEvents = setInterval(refreshEvents, refreshEventsInterval); + return () => clearInterval(intervalEvents); + } + }, [refreshEventsInterval]); + const texts = [ "Preloading all the things...", "Preloading all the things...", @@ -107,7 +142,7 @@ const Startup = (obj) => {

-

{texts[Math.floor(Math.random() * texts.length)]}

+

{texts[Math.floor(Math.random() * texts.length)]}

) diff --git a/src/reducers/livepeer/livepeerstate.js b/src/reducers/livepeer/livepeerstate.js index 883e2ac..a00aeb4 100644 --- a/src/reducers/livepeer/livepeerstate.js +++ b/src/reducers/livepeer/livepeerstate.js @@ -25,7 +25,9 @@ import { SET_ALL_REDEEM_TICKET_EVENTS, SET_ALL_ACTIVATE_EVENTS, SET_ALL_UNBOND_EVENTS, - SET_ALL_STAKE_EVENTS + SET_ALL_STAKE_EVENTS, + SET_ALL_ROUNDS, + SET_ADD_ROUNDS } from "../../actions/livepeer"; export default (state = { @@ -46,6 +48,7 @@ export default (state = { activateEvents: [], unbondEvents: [], stakeEvents: [], + rounds: [] }, { type, message }) => { Object.freeze(state); switch (type) { @@ -132,6 +135,13 @@ export default (state = { return { ...state, unbondEvents: message }; case SET_ALL_STAKE_EVENTS: return { ...state, stakeEvents: message }; + case SET_ALL_ROUNDS: + return { ...state, rounds: message }; + case SET_ADD_ROUNDS: + return { + ...state, + rounds: [...state.rounds, message] + }; default: return { ...state }; } diff --git a/src/util/livepeer.js b/src/util/livepeer.js index 02925c9..5c4dce4 100644 --- a/src/util/livepeer.js +++ b/src/util/livepeer.js @@ -90,24 +90,6 @@ export const getEnsInfo = (addr) => ( }) ); -export const getAllThreeBox = () => ( - fetch("api/livepeer/getAllThreeBox/", { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }) -); - -export const getThreeBox = (addr) => ( - fetch("api/livepeer/getThreeBox/" + addr, { - method: "GET", - headers: { - "Content-Type": "application/json" - } - }) -); - export const getOrchestratorScores = (year, month) => ( fetch("api/livepeer/getOrchestratorScores", { method: "POST", @@ -145,9 +127,10 @@ export const getAllDelInfo = () => ( }) ); -export const getAllMonthlyStats = () => ( +export const getAllMonthlyStats = (smartUpdate) => ( fetch("api/livepeer/getAllMonthlyStats", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } @@ -172,80 +155,108 @@ export const getAllTotalStakes = () => ( }) ); -export const getAllUpdateEvents = () => ( +export const getAllUpdateEvents = (smartUpdate) => ( fetch("api/livepeer/getAllUpdateEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllRewardEvents = () => ( +export const getAllRewardEvents = (smartUpdate) => ( fetch("api/livepeer/getAllRewardEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllClaimEvents = () => ( +export const getAllClaimEvents = (smartUpdate) => ( fetch("api/livepeer/getAllClaimEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllWithdrawStakeEvents = () => ( +export const getAllWithdrawStakeEvents = (smartUpdate) => ( fetch("api/livepeer/getAllWithdrawStakeEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllWithdrawFeesEvents = () => ( +export const getAllWithdrawFeesEvents = (smartUpdate) => ( fetch("api/livepeer/getAllWithdrawFeesEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllTransferTicketEvents = () => ( +export const getAllTransferTicketEvents = (smartUpdate) => ( fetch("api/livepeer/getAllTransferTicketEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllRedeemTicketEvents = () => ( +export const getAllRedeemTicketEvents = (smartUpdate) => ( fetch("api/livepeer/getAllRedeemTicketEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllActivateEvents = () => ( +export const getAllActivateEvents = (smartUpdate) => ( fetch("api/livepeer/getAllActivateEvents", { - method: "GET", + method: "POST", + body: JSON.stringify({ smartUpdate }), headers: { "Content-Type": "application/json" } }) ); -export const getAllUnbondEvents = () => ( +export const getAllUnbondEvents = (smartUpdate) => ( fetch("api/livepeer/getAllUnbondEvents", { + method: "POST", + body: JSON.stringify({ smartUpdate }), + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getAllStakeEvents = (smartUpdate) => ( + fetch("api/livepeer/getAllStakeEvents", { + method: "POST", + body: JSON.stringify({ smartUpdate }), + headers: { + "Content-Type": "application/json" + } + }) +); + +export const hasAnyRefresh = () => ( + fetch("api/livepeer/hasAnyRefresh", { method: "GET", headers: { "Content-Type": "application/json" @@ -253,11 +264,21 @@ export const getAllUnbondEvents = () => ( }) ); -export const getAllStakeEvents = () => ( - fetch("api/livepeer/getAllStakeEvents", { +export const getAllRounds = () => ( + fetch("api/livepeer/getAllRounds", { method: "GET", headers: { "Content-Type": "application/json" } }) +); + +export const getRoundAtBlock = (blockNumber) => ( + fetch("api/livepeer/getRoundAtBlock", { + method: "POST", + body: JSON.stringify({ blockNumber }), + headers: { + 'Content-Type': 'application/json' + } + }) ); \ No newline at end of file