From 988904d4d0b0bd6a1c40d56695e165489bc87a8e Mon Sep 17 00:00:00 2001 From: Marco van Dijk Date: Thu, 3 Mar 2022 10:51:40 +0100 Subject: [PATCH] MVP getting O info using livepeer subgraph api --- backend/src/routes/livepeer.js | 2 - src/actions/livepeer.js | 13 ++ src/eventButton.js | 2 +- src/grafana.js | 220 ++++++++++++++++++------- src/livepeer.js | 8 +- src/loadingScreen.js | 13 +- src/reducers/livepeer/livepeerstate.js | 5 +- src/style.css | 6 +- src/util/livepeer.js | 9 + 9 files changed, 211 insertions(+), 67 deletions(-) diff --git a/backend/src/routes/livepeer.js b/backend/src/routes/livepeer.js index 5155a9f..40fef43 100644 --- a/backend/src/routes/livepeer.js +++ b/backend/src/routes/livepeer.js @@ -70,8 +70,6 @@ const orchQuery = gql` } rewardCut feeShare - pricePerSegment - pendingPricePerSegment pendingFeeShare pendingRewardCut totalStake diff --git a/src/actions/livepeer.js b/src/actions/livepeer.js index 768428e..e176bd9 100644 --- a/src/actions/livepeer.js +++ b/src/actions/livepeer.js @@ -4,6 +4,7 @@ import { receiveErrors } from "./error"; export const RECEIVE_QUOTES = "RECEIVE_QUOTES"; export const RECEIVE_BLOCKCHAIN_DATA = "RECEIVE_BLOCKCHAIN_DATA"; export const RECEIVE_EVENTS = "RECEIVE_EVENTS"; +export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR"; const setQuotes = message => ({ type: RECEIVE_QUOTES, message @@ -14,6 +15,9 @@ const setBlockchainData = message => ({ const setEvents = message => ({ type: RECEIVE_EVENTS, message }); +const setCurrentOrchestratorInfo = message => ({ + type: RECEIVE_ORCHESTRATOR, message +}); export const getQuotes = () => async dispatch => { const response = await apiUtil.getQuotes(); @@ -40,4 +44,13 @@ export const getEvents = () => async dispatch => { return dispatch(setEvents(data)); } return dispatch(receiveErrors(data)); +}; + +export const getCurrentOrchestratorInfo = () => async dispatch => { + const response = await apiUtil.getCurrentOrchestratorInfo(); + const data = await response.json(); + if (response.ok) { + return dispatch(setCurrentOrchestratorInfo(data)); + } + return dispatch(receiveErrors(data)); }; \ No newline at end of file diff --git a/src/eventButton.js b/src/eventButton.js index 665e924..63cf313 100644 --- a/src/eventButton.js +++ b/src/eventButton.js @@ -36,7 +36,7 @@ const EventButton = (obj) => { } else if (obj.name == "TranscoderUpdate") { eventSpecificInfo =
-

O {obj.data.transcoder} changed their rewardCut to {(obj.data.rewardCut / 10000).toFixed(2)} and their feeCut to {(100 - (obj.data.feeShare / 10000)).toFixed(2)}

+

O {obj.data.transcoder} changed their rewardCut to {(obj.data.rewardCut / 10000).toFixed(2)}% and their feeCut to {(100 - (obj.data.feeShare / 10000)).toFixed(2)}%

} else if (obj.name == "TranscoderActivated") { eventSpecificInfo =
diff --git a/src/grafana.js b/src/grafana.js index 0e0ce6c..e4f9e01 100644 --- a/src/grafana.js +++ b/src/grafana.js @@ -1,71 +1,179 @@ -import React, { useEffect, useState } from "react"; +import * as React from "react"; import './style.css'; import { - Navigate, useParams + Navigate } from "react-router-dom"; +import { connect } from "react-redux"; +import { + getQuotes, getCurrentOrchestratorInfo +} from "./actions/livepeer"; -const Grafana = () => { - let params = useParams(); - const [redirectToHome, setRedirectToHome] = useState(false); - - useEffect(() => { - - }, []) - - if (redirectToHome) { - return ; +const mapStateToProps = (state) => { + return { + session: state.session, + userstate: state.userstate, + errors: state.errors, + livepeer: state.livepeerstate } - return ( -
-
- -
+}; + +const mapDispatchToProps = dispatch => ({ + getQuotes: () => dispatch(getQuotes()), + getCurrentOrchestratorInfo: () => dispatch(getCurrentOrchestratorInfo()) +}); + +class Grafana extends React.Component { + state = { + redirectToHome: false, + }; + + constructor(props) { + super(props); + } + + render() { + if (this.state.redirectToHome) { + return ; + } + + let lptPrice = 0; + let ethPrice = 0; + let lptPriceChange24h = 0; + let ethPriceChange24h = 0; + if (this.props.livepeer.quotes) { + if (this.props.livepeer.quotes.LPT) { + lptPrice = this.props.livepeer.quotes.LPT.price.toFixed(2); + lptPriceChange24h = this.props.livepeer.quotes.LPT.percent_change_24h.toFixed(2); + } + if (this.props.livepeer.quotes.ETH) { + ethPrice = this.props.livepeer.quotes.ETH.price.toFixed(2); + ethPriceChange24h = this.props.livepeer.quotes.ETH.percent_change_24h.toFixed(2); + } + } + + console.log(this.props.livepeer); + + let rewardCut = 0; + let feeCut = 0; + let totalStake = 0; + let totalVolumeETH = 0; + let totalVolumeUSD = 0; + let delegators = []; + let delegatorsTotalStake = 0; + let selfStake = 0; + let selfStakeRatio = 0; + if (this.props.livepeer.thisOrchestrator) { + if (this.props.livepeer.thisOrchestrator.rewardCut) { + rewardCut = (this.props.livepeer.thisOrchestrator.rewardCut / 10000).toFixed(2); + } + if (this.props.livepeer.thisOrchestrator.feeShare) { + feeCut = (100 - (this.props.livepeer.thisOrchestrator.feeShare / 10000)).toFixed(2); + } + if (this.props.livepeer.thisOrchestrator.totalStake) { + totalStake = parseFloat(this.props.livepeer.thisOrchestrator.totalStake).toFixed(2); + } + if (this.props.livepeer.thisOrchestrator.totalVolumeETH) { + totalVolumeETH = parseFloat(this.props.livepeer.thisOrchestrator.totalVolumeETH * 1).toFixed(4); + } + if (this.props.livepeer.thisOrchestrator.totalVolumeUSD) { + totalVolumeUSD = parseFloat(this.props.livepeer.thisOrchestrator.totalVolumeUSD * 1).toFixed(2); + } + if (this.props.livepeer.thisOrchestrator.delegators && this.props.livepeer.thisOrchestrator.delegator) { + delegators = this.props.livepeer.thisOrchestrator.delegators; + selfStake = parseFloat(this.props.livepeer.thisOrchestrator.delegator.bondedAmount); + { + delegators.map((delObj, idx) => { + delegatorsTotalStake += parseFloat(delObj.bondedAmount); + }) + } + selfStakeRatio = ((selfStake / delegatorsTotalStake) * 100).toFixed(2); + delegatorsTotalStake = delegatorsTotalStake.toFixed(2); + selfStake = selfStake.toFixed(2); + } + } + + return (
-
-
-
- -
-
- - -
-
- -
-
- -
-
- -
-
- -
-
- -
+
+ +
+
+
+
+
+
+
+
+
+

Price Info

+
+
+ +

${lptPrice}

+

({lptPriceChange24h}%)

+
+
+ +

${ethPrice}

+

({ethPriceChange24h}%)

+
+
+
+
+

Orchestrator Info

+
+
+

Reward Cut {rewardCut}%

+

Fee Cut {feeCut}%

+
+
+

Total Stake {totalStake} LPT

+

Earned fees {totalVolumeETH} Eth (${totalVolumeUSD})

+
+
+

Self stake {selfStake} LPT (Ratio of {selfStakeRatio}%)

+

Total stake {delegatorsTotalStake} LPT

+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
-
- ); + ); + } } -export default Grafana; \ No newline at end of file +export default connect( + mapStateToProps, + mapDispatchToProps +)(Grafana); diff --git a/src/livepeer.js b/src/livepeer.js index f898962..812977b 100644 --- a/src/livepeer.js +++ b/src/livepeer.js @@ -3,10 +3,9 @@ import './style.css'; import { Navigate } from "react-router-dom"; -import ScrollContainer from 'react-indiana-drag-scroll'; import { connect } from "react-redux"; import { - getQuotes, getBlockchainData, getEvents + getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo } from "./actions/livepeer"; import EventViewer from "./eventViewer"; @@ -22,7 +21,8 @@ const mapStateToProps = (state) => { const mapDispatchToProps = dispatch => ({ getQuotes: () => dispatch(getQuotes()), getBlockchainData: () => dispatch(getBlockchainData()), - getEvents: () => dispatch(getEvents()) + getEvents: () => dispatch(getEvents()), + getCurrentOrchestratorInfo: () => dispatch(getCurrentOrchestratorInfo()) }); class Livepeer extends React.Component { @@ -38,9 +38,11 @@ class Livepeer extends React.Component { this.props.getQuotes(); this.props.getBlockchainData(); this.props.getEvents(); + this.props.getCurrentOrchestratorInfo(); } render() { + console.log(this.props.livepeer.thisOrchestrator); if (this.state.redirectToHome) { return ; } diff --git a/src/loadingScreen.js b/src/loadingScreen.js index 9383a7f..74da480 100644 --- a/src/loadingScreen.js +++ b/src/loadingScreen.js @@ -3,6 +3,9 @@ import { connect } from "react-redux"; import { getVisitorStats } from "./actions/user"; +import { + getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo +} from "./actions/livepeer"; import { login } from "./actions/session"; const mapStateToProps = (state) => { @@ -15,7 +18,11 @@ const mapStateToProps = (state) => { const mapDispatchToProps = dispatch => ({ getVisitorStats: () => dispatch(getVisitorStats()), - login: () => dispatch(login()) + login: () => dispatch(login()), + getQuotes: () => dispatch(getQuotes()), + getBlockchainData: () => dispatch(getBlockchainData()), + getEvents: () => dispatch(getEvents()), + getCurrentOrchestratorInfo: () => dispatch(getCurrentOrchestratorInfo()) }); @@ -23,6 +30,10 @@ class Startup extends React.Component { componentDidMount() { this.props.login(); this.props.getVisitorStats(); + this.props.getQuotes(); + this.props.getBlockchainData(); + this.props.getEvents(); + this.props.getCurrentOrchestratorInfo(); } render() { return this.props.children; diff --git a/src/reducers/livepeer/livepeerstate.js b/src/reducers/livepeer/livepeerstate.js index bb7d2e4..e2ff91b 100644 --- a/src/reducers/livepeer/livepeerstate.js +++ b/src/reducers/livepeer/livepeerstate.js @@ -1,7 +1,8 @@ import { RECEIVE_QUOTES, RECEIVE_BLOCKCHAIN_DATA, - RECEIVE_EVENTS + RECEIVE_EVENTS, + RECEIVE_ORCHESTRATOR } from "../../actions/livepeer"; export default (state = {}, { type, message }) => { @@ -13,6 +14,8 @@ export default (state = {}, { type, message }) => { return { ...state, blockchains: message }; case RECEIVE_EVENTS: return { ...state, events: message }; + case RECEIVE_ORCHESTRATOR: + return { ...state, thisOrchestrator: message.transcoders[0] }; default: return { ...state }; } diff --git a/src/style.css b/src/style.css index ad4cff6..b13510d 100644 --- a/src/style.css +++ b/src/style.css @@ -189,7 +189,7 @@ svg { color: rgba(162, 161, 255, 0.5); } -.hostinfo { +.hostInfo { cursor: default; text-align: start; padding: 10px; @@ -197,9 +197,9 @@ svg { user-select: text; margin-top: 0; margin-bottom: 0; - font-size: x-small; + font-size: small; color: rgba(15, 15, 15, 0.8750); - background-color: rgba(255, 255, 255, 0.06); + background-color: rgba(169, 177, 214, 0.8); -webkit-box-shadow: inset 3px 3px 12px 2px rgba(28, 28, 170, 0.2); -moz-box-shadow: inset 3px 3px 12px 2px rgba(28, 28, 170, 0.2); box-shadow: inset 3px 3px 12px 2px rgba(28, 28, 170, 0.2); diff --git a/src/util/livepeer.js b/src/util/livepeer.js index 0ee325e..58c5781 100644 --- a/src/util/livepeer.js +++ b/src/util/livepeer.js @@ -25,4 +25,13 @@ export const getEvents = () => ( "Content-Type": "application/json" } }) +); + +export const getCurrentOrchestratorInfo = () => ( + fetch("api/livepeer/getOrchestrator", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) ); \ No newline at end of file