mirror of
https://github.com/stronk-dev/LivepeerEvents.git
synced 2025-07-05 10:45:10 +02:00
Big layout update
This commit is contained in:
parent
1db2a934a2
commit
fcdc274014
@ -7,6 +7,9 @@ const Block = (obj) => {
|
||||
const [thisDate, thisTime] = dateObj.toISOString().split('T');
|
||||
return (
|
||||
<div className="rowAlignLeft" style={{ width: '100%', marginTop: '1em' }}>
|
||||
<a className="selectOrch" href={obj.url}>
|
||||
<img alt="" src="arb.svg" width="30em" height="30em" />
|
||||
</a>
|
||||
<span className="rowAlignRight elipsText">
|
||||
<a className="selectOrch" href={"https://arbiscan.io/block/" + obj.block}>
|
||||
🔗{obj.block}
|
||||
|
@ -3,9 +3,9 @@ import ReactTooltip from "react-tooltip";
|
||||
|
||||
const Address = (obj) => {
|
||||
return (
|
||||
<div className="rowAlignLeft" style={{ width: 'unset' }}>
|
||||
<div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}>
|
||||
<a className="selectOrchLight" href={"https://explorer.livepeer.org/accounts/" + obj.address} data-tip data-for={obj.seed} >
|
||||
<div className="rowAlignLeft" style={{ width: 'unset' }}>
|
||||
<div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}>
|
||||
<img alt="" src="livepeer.png" width="20" height="20" />
|
||||
<span className="elipsText">{obj.address}</span>
|
||||
</div>
|
||||
|
47
src/OrchDelegatorViewer.js
Normal file
47
src/OrchDelegatorViewer.js
Normal file
@ -0,0 +1,47 @@
|
||||
import React from "react";
|
||||
import ScrollContainer from "react-indiana-drag-scroll";
|
||||
import Address from "./OrchAddressViewer";
|
||||
|
||||
const OrchDelegatorViewer = (obj) => {
|
||||
let delegators = obj.delegators;
|
||||
if (delegators && delegators.length) {
|
||||
return (
|
||||
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<div className="row" style={{ margin: '0' }}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>{delegators.length} Current Delegators</h3>
|
||||
</div>
|
||||
<div className="content-wrapper">
|
||||
<ScrollContainer className="overflow-container" hideScrollbars={false}>
|
||||
<div className="overflow-content" style={{ cursor: 'grab', padding: 0, maxHeight: '300px' }}>
|
||||
{
|
||||
delegators.map((delObj, idx) => {
|
||||
return (
|
||||
<div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} key={"delegator" + idx} style={{ margin: 0, textAlign: 'center',alignItems: 'center', justifyContent:'center' }}>
|
||||
<Address address={delObj.id} seed={"delegator" + idx + delObj.id} />
|
||||
<div className="rowAlignRight" style={{ margin: 0 }}>
|
||||
<p className="darkText">{parseFloat(delObj.bondedAmount).toFixed(2)} LPT since round {delObj.startRound}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<div className="row" style={{ margin: '0' }}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>The selected Orchestrator has no Delegators</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default OrchDelegatorViewer;
|
115
src/OrchInfoViewer.js
Normal file
115
src/OrchInfoViewer.js
Normal file
@ -0,0 +1,115 @@
|
||||
import React from "react";
|
||||
import Stat from "./statViewer";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import Address from "./OrchAddressViewer";
|
||||
|
||||
function updateClipboard(newClip) {
|
||||
navigator.clipboard.writeText(newClip).then(
|
||||
() => {
|
||||
console.log("Copied!");
|
||||
},
|
||||
() => {
|
||||
console.log("Copy failed!");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function copyLink(addr) {
|
||||
navigator.permissions
|
||||
.query({ name: "clipboard-write" })
|
||||
.then((result) => {
|
||||
if (result.state === "granted" || result.state === "prompt") {
|
||||
updateClipboard(addr);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const OrchInfoViewer = (obj) => {
|
||||
let rewardCut = 0;
|
||||
let feeCut = 0;
|
||||
let totalStake = 0;
|
||||
let totalVolumeETH = 0;
|
||||
let totalVolumeUSD = 0;
|
||||
let selfStake = 0;
|
||||
let selfStakeRatio = 0;
|
||||
let thisUrl = "";
|
||||
let thisID = "";
|
||||
if (obj.totalStake && obj.totalStake > 0) {
|
||||
if (obj.rewardCut) {
|
||||
rewardCut = (obj.rewardCut / 10000).toFixed(2);
|
||||
}
|
||||
if (obj.feeShare) {
|
||||
feeCut = (100 - (obj.feeShare / 10000)).toFixed(2);
|
||||
}
|
||||
if (obj.totalStake) {
|
||||
totalStake = parseFloat(obj.totalStake).toFixed(2);
|
||||
}
|
||||
if (obj.totalVolumeETH) {
|
||||
totalVolumeETH = parseFloat(obj.totalVolumeETH * 1).toFixed(4);
|
||||
}
|
||||
if (obj.totalVolumeUSD) {
|
||||
totalVolumeUSD = parseFloat(obj.totalVolumeUSD * 1).toFixed(2);
|
||||
}
|
||||
if (obj.delegator) {
|
||||
selfStake = parseFloat(obj.delegator.bondedAmount);
|
||||
selfStakeRatio = ((selfStake / totalStake) * 100).toFixed(2);
|
||||
selfStake = selfStake.toFixed(2);
|
||||
thisID = obj.delegator.id;
|
||||
thisUrl = "https://explorer.livepeer.org/accounts/" + thisID;
|
||||
}
|
||||
|
||||
let shareUrl;
|
||||
if (obj.rootOnly) {
|
||||
shareUrl = window.location.href;
|
||||
} else {
|
||||
let thisFullPath = window.location.href;
|
||||
if (thisFullPath.lastIndexOf("?") > -1) {
|
||||
thisFullPath = thisFullPath.substring(0, thisFullPath.lastIndexOf("?"));
|
||||
}
|
||||
shareUrl = thisFullPath + "?orchAddr=" + thisID;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="row" style={{ width: 'unset', }}>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<div style={{ flexDirection: 'row', display: "flex", borderBottom: '2px solid rgba(15,15,15,0.05)', marginTop: '1em' }}>
|
||||
<a href={thisUrl}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>Orchestrator Info</h3>
|
||||
<Address address={thisID} />
|
||||
</a>
|
||||
</div>
|
||||
<div className="row" style={{ margin: 0 }}>
|
||||
<Stat header={"Earned Fees"} content1={totalVolumeETH + " Eth"} content2={"$" + totalVolumeUSD} />
|
||||
</div>
|
||||
<div className="row" style={{ margin: 0 }}>
|
||||
<Stat header={"Commission"} title1={"Reward"} content1={rewardCut + "%"} title2={"Fee"} content2={feeCut + "%"} />
|
||||
</div>
|
||||
<div className="row" style={{ margin: 0 }}>
|
||||
<Stat header={"Stake"} title1={"Total"} content1={totalStake + " LPT"} title2={"Self"} content2={selfStake + " LPT (" + selfStakeRatio + ")%"} />
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<button style={{ marginBottom: '1em' }} className="selectOrchLight" data-tip data-for="registerTip" onClick={() => {
|
||||
copyLink(shareUrl);
|
||||
}}>
|
||||
<img alt="" src="clipboard.svg" width="20em" height="20em" />
|
||||
</button>
|
||||
<ReactTooltip id="registerTip" place="top" effect="solid">
|
||||
Copy to clipboard
|
||||
</ReactTooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="row" style={{ width: 'unset', marginBottom: '1em', marginTop: '1em' }}>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<div className="row" style={{ margin: '0' }}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>The selected Orchestrator is currently inactive</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default OrchInfoViewer;
|
@ -17,6 +17,7 @@ export const RECEIVE_BLOCKCHAIN_DATA = "RECEIVE_BLOCKCHAIN_DATA";
|
||||
export const RECEIVE_EVENTS = "RECEIVE_EVENTS";
|
||||
export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR";
|
||||
export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR";
|
||||
export const CLEAR_ORCHESTRATOR = "CLEAR_ORCHESTRATOR";
|
||||
|
||||
const setQuotes = message => ({
|
||||
type: RECEIVE_QUOTES, message
|
||||
@ -33,6 +34,9 @@ const setCurrentOrchestratorInfo = message => ({
|
||||
const setOrchestratorInfo = message => ({
|
||||
type: RECEIVE_ORCHESTRATOR, message
|
||||
});
|
||||
const clearOrchestratorInfo = () => ({
|
||||
type: CLEAR_ORCHESTRATOR
|
||||
})
|
||||
|
||||
export const getQuotes = () => async dispatch => {
|
||||
const response = await apiUtil.getQuotes();
|
||||
@ -127,7 +131,7 @@ export const getEvents = () => async dispatch => {
|
||||
else if (eventContainsRebond) {
|
||||
eventType = "Stake";
|
||||
eventColour = stakeColour;
|
||||
eventDescription = "increased their stake to " + tmpAmount.toFixed(2) + " LPT at";
|
||||
eventDescription = "is now staking " + tmpAmount.toFixed(2) + " LPT";
|
||||
}
|
||||
|
||||
// Fill description of Stake Event if it wasn't set yet
|
||||
@ -136,7 +140,7 @@ export const getEvents = () => async dispatch => {
|
||||
eventDescription = "staked " + tmpAmount.toFixed(2) + " LPT";
|
||||
} else if (eventFrom === eventTo) {
|
||||
eventFrom = "";
|
||||
eventDescription = "increased their stake to " + tmpAmount.toFixed(2) + " LPT";
|
||||
eventDescription = "is now staking " + tmpAmount.toFixed(2) + " LPT";
|
||||
} else {
|
||||
eventDescription = "moved a " + tmpAmount.toFixed(2) + " LPT stake";
|
||||
}
|
||||
@ -370,3 +374,7 @@ export const getOrchestratorInfo = (orchAddr) => async dispatch => {
|
||||
}
|
||||
return dispatch(receiveErrors(data));
|
||||
};
|
||||
|
||||
export const clearOrchestrator = () => async dispatch => {
|
||||
return dispatch(clearOrchestratorInfo({}));
|
||||
};
|
@ -10,7 +10,7 @@ import Block from "./BlockViewer";
|
||||
const EventButton = (obj) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
let eventArrow;
|
||||
|
||||
let eventTo;
|
||||
let eventFrom;
|
||||
let eventCaller;
|
||||
@ -21,13 +21,14 @@ const EventButton = (obj) => {
|
||||
if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") {
|
||||
obj.eventObj.eventTo = "";
|
||||
}
|
||||
if (obj.eventObj.eventTo !== "" || obj.eventObj.eventFrom !== "") {
|
||||
eventArrow = <p style={{marginRight: 0}}>→</p>;
|
||||
}
|
||||
if (obj.eventObj.eventTo || obj.eventObj.eventFrom || obj.eventObj.eventCaller) {
|
||||
if (obj.eventObj.eventTo) {
|
||||
eventTo =
|
||||
<div className="rowAlignRight" style={{ width: 'unset', marginLeft: 0 }}>
|
||||
<div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
|
||||
<p>To</p>
|
||||
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventTo}>
|
||||
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a>
|
||||
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventTo) }} >
|
||||
<span className="elipsText">🔎</span>
|
||||
</button>
|
||||
@ -38,7 +39,11 @@ const EventButton = (obj) => {
|
||||
}
|
||||
if (obj.eventObj.eventFrom) {
|
||||
eventFrom =
|
||||
<div className="rowAlignRight" style={{ width: 'unset', margin: 0 }}>
|
||||
<div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
|
||||
<p>From</p>
|
||||
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventFrom}>
|
||||
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a>
|
||||
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventFrom) }} >
|
||||
<span className="elipsText">🔎</span>
|
||||
</button>
|
||||
@ -49,7 +54,11 @@ const EventButton = (obj) => {
|
||||
}
|
||||
if (obj.eventObj.eventCaller) {
|
||||
eventCaller =
|
||||
<div className="rowAlignLeft" style={{ width: 'unset', margin: 0 }}>
|
||||
<div className="rowAlignLeft" style={{ width: '100%', margin: 0, marginLeft: '0.5em' }}>
|
||||
<p>Caller</p>
|
||||
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventCaller}>
|
||||
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a>
|
||||
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventCaller) }} >
|
||||
<span className="elipsText">🔎</span>
|
||||
</button>
|
||||
@ -58,40 +67,29 @@ const EventButton = (obj) => {
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
eventRightAddr = <div className="rowAlignRight" style={{ width: 'unset', padding: 0, margin: 0 }}>
|
||||
{eventFrom}
|
||||
{eventArrow}
|
||||
{eventTo}
|
||||
eventRightAddr = <div className="strokeSmollLeft" style={{ width: 'unset', padding: 0, margin: 0 }}>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
let blockNumber;
|
||||
if (obj.isFirstOfBlock) {
|
||||
blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} />
|
||||
blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} url={obj.eventObj.transactionUrl} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="stroke" style={{ width: '100%', padding: 0, margin: 0 }}>
|
||||
{blockNumber}
|
||||
<div className="rowAlignLeft" style={{ backgroundColor: obj.eventObj.eventColour, borderRadius: "1.2em", width: '100%' }}>
|
||||
<div className="rowAlignLeft" style={{ flex: '1', width: 'unset' }}>
|
||||
<a className="selectOrch" href={obj.eventObj.transactionUrl}>
|
||||
<img alt="" src="arb.svg" width="30" height="30" />
|
||||
</a>
|
||||
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventCaller}>
|
||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||
</a>
|
||||
<div className="rowAlignLeft" style={{ flex: '1', width: '100%', padding: 0, margin: 0 }}>
|
||||
{eventCaller}
|
||||
</div>
|
||||
<div className="rowAlignLeft" style={{ borderRadius: "1.2em", backgroundColor: obj.eventObj.eventColour, padding: 0, margin: 0 }}>
|
||||
<div className="strokeSmollLeft">
|
||||
{eventCaller}
|
||||
<p className="rowAlignLeft withWrap" style={{ width: '100%' }}>
|
||||
💬 {obj.eventObj.eventDescription}
|
||||
</p>
|
||||
{eventFrom}
|
||||
{eventTo}
|
||||
</div>
|
||||
<div className="rowAlignLeft" style={{ flex: '2', width: 'unset', padding: 0, margin: 0 }}>
|
||||
<span className="rowAlignLeft elipsText">
|
||||
{obj.eventObj.eventDescription}
|
||||
</span>
|
||||
{eventRightAddr}
|
||||
</div>
|
||||
</div >
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ const defaultMaxShown = 100;
|
||||
const defaultIncrementMaxShown = 100;
|
||||
|
||||
const EventViewer = (obj) => {
|
||||
const [searchTerm, setSearchTerm] = useState(obj.prefill || "");
|
||||
const [amountFilter, setAmountFilter] = useState("0");
|
||||
const [maxAmount, setMaxAmount] = useState(defaultMaxShown);
|
||||
const [filterActivated, setFilterActivated] = useState(true);
|
||||
@ -49,35 +48,29 @@ const EventViewer = (obj) => {
|
||||
let prevBlock = 0;
|
||||
let showMoreBlock;
|
||||
if (maxAmount < limitShown) {
|
||||
showMoreBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
setMaxAmount(maxAmount + defaultIncrementMaxShown);
|
||||
}}>
|
||||
<h3>Show more</h3>
|
||||
</button>
|
||||
</div>
|
||||
showMoreBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
setMaxAmount(maxAmount + defaultIncrementMaxShown);
|
||||
}}>
|
||||
<h3>Show more</h3>
|
||||
</button>
|
||||
}
|
||||
let showLessBlock;
|
||||
if (defaultMaxShown < maxAmount) {
|
||||
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
setMaxAmount(defaultMaxShown);
|
||||
}}>
|
||||
<h3>Show {defaultMaxShown}</h3>
|
||||
</button>
|
||||
</div>
|
||||
showLessBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
setMaxAmount(defaultMaxShown);
|
||||
}}>
|
||||
<h3>Show {defaultMaxShown}</h3>
|
||||
</button>
|
||||
} else {
|
||||
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '5em' }}></div>
|
||||
}
|
||||
|
||||
let searchTermText;
|
||||
if (searchTerm !== "") {
|
||||
if (searchTerm.length > 15) {
|
||||
searchTermText = <h3>Only showing addresses containing {searchTerm.substring(0, 15)}...</h3>
|
||||
if (obj.searchTerm !== "") {
|
||||
if (obj.searchTerm.length > 15) {
|
||||
searchTermText = <h3>Only showing addresses containing {obj.searchTerm.substring(0, 15)}...</h3>
|
||||
} else {
|
||||
searchTermText = <h3>Only showing addresses containing {searchTerm}</h3>
|
||||
searchTermText = <h3>Only showing addresses containing {obj.searchTerm}</h3>
|
||||
}
|
||||
} else {
|
||||
searchTermText = <h3>Filter by Orchestrator address</h3>
|
||||
@ -95,11 +88,11 @@ const EventViewer = (obj) => {
|
||||
}
|
||||
}
|
||||
// Filter name on from, to, caller
|
||||
if (searchTerm !== "") {
|
||||
if (obj.searchTerm !== "") {
|
||||
let isFiltered = true;
|
||||
if (eventObj.eventCaller.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (eventObj.eventFrom.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (eventObj.eventTo.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (eventObj.eventCaller.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (eventObj.eventFrom.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (eventObj.eventTo.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||
if (isFiltered) continue;
|
||||
}
|
||||
// Filter Events on filter buttons
|
||||
@ -164,7 +157,7 @@ const EventViewer = (obj) => {
|
||||
eventList.push(<EventButton
|
||||
key={eventObj.transactionHash + unfiltered}
|
||||
eventObj={eventObj}
|
||||
setSearchTerm={setSearchTerm}
|
||||
setSearchTerm={obj.setSearchTerm}
|
||||
/>);
|
||||
} else {
|
||||
prevBlock = eventObj.transactionBlock;
|
||||
@ -173,81 +166,69 @@ const EventViewer = (obj) => {
|
||||
eventObj={eventObj}
|
||||
isFirstOfBlock={prevBlock}
|
||||
time={eventObj.transactionTime}
|
||||
setSearchTerm={setSearchTerm}
|
||||
setSearchTerm={obj.setSearchTerm}
|
||||
/>);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="stroke roundedOpaque" style={{ padding: 0, margin: 0, marginTop: '2em', position: 'absolute', bottom: 0, top: '300px', overflowY: 'auto', overflowX: 'hidden', width: 'unset' }}>
|
||||
<div className="row showNeverOnMobile">
|
||||
<div className="row">
|
||||
{showLessBlock}
|
||||
let filterBit;
|
||||
if (obj.showFilter) {
|
||||
filterBit = <div className="row roundedOpaque" style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, borderBottomLeftRadius: 0, margin: 0 }}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 1 }}>
|
||||
<div className="stroke" style={{ margin: "0", padding: 0 }}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3>Showing max {maxAmount} results</h3>
|
||||
</div>
|
||||
{showMoreBlock}
|
||||
</div>
|
||||
<div className="row">
|
||||
<div className="stroke" style={{ margin: "0", padding: 0 }}>
|
||||
{searchTermText}
|
||||
<input className="searchField" style={{ width: '100%' }}
|
||||
value={searchTerm}
|
||||
onChange={(evt) => setSearchTerm(evt.target.value)}
|
||||
placeholder='Filter by Orchestrator address'
|
||||
type="text"
|
||||
/>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
{showLessBlock}
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
{showMoreBlock}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="row">
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 2 }}>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
{searchTermText}
|
||||
</div>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<input className="searchField" style={{ width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
|
||||
value={obj.searchTerm}
|
||||
onChange={(evt) => obj.setSearchTerm(evt.target.value)}
|
||||
placeholder='Filter by Orchestrator address'
|
||||
type="text"
|
||||
/>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '6em' }} onClick={() => {
|
||||
obj.setSearchTerm("");
|
||||
}}>
|
||||
<h3>Clear</h3>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 2 }}>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<h3>{parseFloat(amountFilter) > 0 ? ("Only showing higher than " + amountFilter) : "Filter by minimum value"}</h3>
|
||||
</div>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal - 1000);
|
||||
setAmountFilter(0);
|
||||
}}>
|
||||
<h3>-1000</h3>
|
||||
<h3>0</h3>
|
||||
</button>
|
||||
</div>
|
||||
<input className="searchField" style={{ margin: 0, padding: 0, height: '2em', width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
|
||||
value={amountFilter}
|
||||
onChange={(evt) => setAmountFilter(evt.target.value)}
|
||||
placeholder='Filter by minimum value'
|
||||
type="number"
|
||||
/>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal - 100);
|
||||
}}>
|
||||
<h3>-100</h3>
|
||||
</button>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '3em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal - 10);
|
||||
}}>
|
||||
<h3>-10</h3>
|
||||
</button>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: "0", padding: 0 }}>
|
||||
<h3>{parseFloat(amountFilter) > 0 ? ("Only showing higher than " + amountFilter) : "Filter by minimum value"}</h3>
|
||||
<input className="searchField" style={{ margin: 0, padding: 0, height: '2em', width: '80%', paddingLeft: '1em', paddingRight: '1em' }}
|
||||
value={amountFilter}
|
||||
onChange={(evt) => setAmountFilter(evt.target.value)}
|
||||
placeholder='Filter by minimum value'
|
||||
type="number"
|
||||
/>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '3em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal + 10);
|
||||
}}>
|
||||
<h3>+10</h3>
|
||||
</button>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal + 100);
|
||||
@ -256,7 +237,6 @@ const EventViewer = (obj) => {
|
||||
</button>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3></h3>
|
||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||
const curVal = parseFloat(amountFilter);
|
||||
setAmountFilter(curVal + 1000);
|
||||
@ -266,48 +246,60 @@ const EventViewer = (obj) => {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="content-wrapper" style={{ alignItems: 'stretch', width: '100%' }}>
|
||||
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}>
|
||||
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0}}>
|
||||
{eventList}
|
||||
</div>
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="strokeSmollLeft" style={{ padding: 0, margin: 0, height: 'calc( 100vh - 50px)' }}>
|
||||
{filterBit}
|
||||
<div className="row" style={{ padding: 0, margin: 0, width: '100%', height: '100%' }}>
|
||||
<div className="stroke roundedOpaque" style={{ padding: 0, margin: 0, width: 'unset', height: '100%', marginRight: '1em', overflow: 'hidden', marginTop: '1em', overflowX: 'scroll' }}>
|
||||
<div className="content-wrapper" style={{ width: '100%' }}>
|
||||
<ScrollContainer className="overflow-container" hideScrollbars={false}>
|
||||
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0 }}>
|
||||
<div className={obj.forceVertical ? "flexContainer forceWrap" : "flexContainer"} style={{ margin: 0, textAlign: 'center', alignItems: 'center', justifyContent: 'center' }}>
|
||||
{eventList}
|
||||
</div>
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
<div className="strokeSmollLeft" style={{ marginRight: "1em" }}>
|
||||
<button className={filterActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: filterActivatedColour }} onClick={() => {
|
||||
setFilterActivated(!filterActivated);
|
||||
}}>
|
||||
<h3>Activated</h3>
|
||||
</button>
|
||||
<button className={rewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: rewardActivatedColour }} onClick={() => {
|
||||
setRewardActivated(!rewardActivated);
|
||||
}}>
|
||||
<h3>Reward</h3>
|
||||
</button>
|
||||
<button className={updateActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: updateActivatedColour }} onClick={() => {
|
||||
setUpdateActivated(!updateActivated);
|
||||
}}>
|
||||
<h3>Update</h3>
|
||||
</button>
|
||||
<button className={withdrawActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: withdrawActivatedColour }} onClick={() => {
|
||||
setWithdrawActivated(!withdrawActivated);
|
||||
}}>
|
||||
<h3>Withdraw</h3>
|
||||
</button>
|
||||
<button className={stakeActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: stakeActivatedColour }} onClick={() => {
|
||||
setStakeActivated(!stakeActivated);
|
||||
}}>
|
||||
<h3>Stake</h3>
|
||||
</button>
|
||||
<button className={delegatorRewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: delegatorActivatedColour }} onClick={() => {
|
||||
setDelegatorRewardActivated(!delegatorRewardActivated);
|
||||
}}>
|
||||
<h3>Claim</h3>
|
||||
</button>
|
||||
<button className={unbondActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: unbondActivatedColour }} onClick={() => {
|
||||
setUnbondActivated(!unbondActivated);
|
||||
}}>
|
||||
<h3>Unbond</h3>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
<div className="strokeSmollLeft" style={{ marginRight: "1em" }}>
|
||||
<button className={filterActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: filterActivatedColour }} onClick={() => {
|
||||
setFilterActivated(!filterActivated);
|
||||
}}>
|
||||
<h3>Activated</h3>
|
||||
</button>
|
||||
<button className={rewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: rewardActivatedColour }} onClick={() => {
|
||||
setRewardActivated(!rewardActivated);
|
||||
}}>
|
||||
<h3>Reward</h3>
|
||||
</button>
|
||||
<button className={updateActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: updateActivatedColour }} onClick={() => {
|
||||
setUpdateActivated(!updateActivated);
|
||||
}}>
|
||||
<h3>Update</h3>
|
||||
</button>
|
||||
<button className={withdrawActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: withdrawActivatedColour }} onClick={() => {
|
||||
setWithdrawActivated(!withdrawActivated);
|
||||
}}>
|
||||
<h3>Withdraw</h3>
|
||||
</button>
|
||||
<button className={stakeActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: stakeActivatedColour }} onClick={() => {
|
||||
setStakeActivated(!stakeActivated);
|
||||
}}>
|
||||
<h3>Stake</h3>
|
||||
</button>
|
||||
<button className={delegatorRewardActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: delegatorActivatedColour }} onClick={() => {
|
||||
setDelegatorRewardActivated(!delegatorRewardActivated);
|
||||
}}>
|
||||
<h3>Claim</h3>
|
||||
</button>
|
||||
<button className={unbondActivated ? "row nonHomeButton active" : "row nonHomeButton"} style={{ backgroundColor: unbondActivatedColour }} onClick={() => {
|
||||
setUnbondActivated(!unbondActivated);
|
||||
}}>
|
||||
<h3>Unbond</h3>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -44,7 +44,7 @@ const Grafana = (obj) => {
|
||||
<div className="flexContainer">
|
||||
<div className="stroke" style={{ marginTop: 0, marginBottom: 5, paddingBottom: 0 }}>
|
||||
<div className="stroke roundedOpaque" style={{}}>
|
||||
<div className="row">
|
||||
<div className="flexContainer" style={{ margin: 0, textAlign: 'center',alignItems: 'center', justifyContent:'center' }}>
|
||||
<div className="row">
|
||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||
<p>${lptPrice}</p>
|
||||
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
|
||||
import './style.css';
|
||||
import { Navigate, useSearchParams } from "react-router-dom";
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
import { getOrchestratorInfo } from "./actions/livepeer";
|
||||
import { getOrchestratorInfo, clearOrchestrator } from "./actions/livepeer";
|
||||
import EventViewer from "./eventViewer";
|
||||
import Orchestrator from "./orchestratorViewer";
|
||||
import Stat from "./statViewer";
|
||||
@ -11,14 +11,18 @@ import Stat from "./statViewer";
|
||||
|
||||
const Livepeer = (obj) => {
|
||||
const [prefill, setPrefill] = useSearchParams();
|
||||
const [searchTerm, setSearchTerm] = useState("");
|
||||
const dispatch = useDispatch();
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const [redirectToHome, setRedirectToHome] = useState(false);
|
||||
const [showFilter, setShowFilter] = useState(false);
|
||||
const [showSidebar, setShowSidebar] = useState(true);
|
||||
console.log("Rendering Livepeer");
|
||||
|
||||
useEffect(() => {
|
||||
if (prefill.get('orchAddr') && prefill.get('orchAddr') !== "") {
|
||||
dispatch(getOrchestratorInfo(prefill.get('orchAddr')));
|
||||
setSearchTerm(prefill.get('orchAddr'));
|
||||
}
|
||||
}, [prefill]);
|
||||
|
||||
@ -123,36 +127,72 @@ const Livepeer = (obj) => {
|
||||
}
|
||||
|
||||
let thisOrchObj;
|
||||
let headerString;
|
||||
if (livepeer.selectedOrchestrator) {
|
||||
thisOrchObj = livepeer.selectedOrchestrator;
|
||||
headerString = "Inspecting " + thisOrchObj.id;
|
||||
} else {
|
||||
headerString = "Livepeer Orchestrator Explorer";
|
||||
}
|
||||
|
||||
let sidebar;
|
||||
if (showSidebar){
|
||||
sidebar = <div id='sideContent'>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '100%', marginTop: '1em' }}>
|
||||
<div className="row" style={{ alignItems: 'stretch', height: '100%', padding: '0.2em', width: "unset" }}>
|
||||
<Orchestrator thisOrchestrator={thisOrchObj} rootOnly={false} forceVertical={true} />
|
||||
</div>
|
||||
<div className="stroke metaSidebar" style={{ padding: 0, maxWidth: "300px" }}>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<h3 style={{ margin: 0, padding: 0 }}>Smart contract prices</h3>
|
||||
</div>
|
||||
<div className="stroke" style={{ margin: 0, padding: 0 }}>
|
||||
<Stat header={"Reward Call"} content1={"$" + redeemRewardCostL2USD + " (vs " + redeemRewardCostL1USD + " on L1)"} />
|
||||
<Stat header={"Claim Ticket"} content1={"$" + claimTicketCostL2USD + " (vs " + claimTicketCostL1USD + " on L1)"} />
|
||||
<Stat header={"Staking Fees"} content1={"$" + stakeFeeCostL2USD + " (vs " + stakeFeeCostL1USD + " on L1)"} />
|
||||
<Stat header={"Change Commission"} content1={"$" + commissionFeeCostL2USD + " (vs " + commissionFeeCostL1USD + " on L1)"} />
|
||||
<Stat header={"Change URI"} content1={"$" + serviceUriFeeCostL2USD + " (vs " + serviceUriFeeCostL1USD + " on L1)"} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div >
|
||||
}
|
||||
|
||||
return (
|
||||
<div style={{ width: '100%', height: '100%' }}>
|
||||
<div className="row" style={{ margin: 0, padding: 0, backgroundColor: "rgba(180, 175, 252, 0.80)", boxSizing: "border-box", backdropDilter: "blur(6px)", boxSshadow: "9px 13px 18px 8px rgba(8, 7, 56, 0.692)", position: 'absolute', top: '0px', left: '0px', height: '300px', right: '0px', overflow: 'hidden' }}>
|
||||
<button className="homeButton" onClick={() => {
|
||||
setRedirectToHome(true);
|
||||
}}>
|
||||
<img alt="" src="livepeer.png" width="100em" height="100em" />
|
||||
</button>
|
||||
<div className="row" style={{ alignItems: 'stretch', height: '100%', flex: 2, padding: '0.2em', maxWidth: "1100px" }}>
|
||||
<Orchestrator thisOrchestrator={thisOrchObj} rootOnly={false} />
|
||||
<div style={{ margin: 0, padding: 0, height: '100%', width: '100%', overflow: 'hidden' }}>
|
||||
<div id='header'>
|
||||
<div className='rowAlignLeft'>
|
||||
<button className="homeButton" onClick={() => {
|
||||
setRedirectToHome(true);
|
||||
}}>
|
||||
<h1 style={{margin: 0, padding: 0}}>🏠</h1>
|
||||
</button>
|
||||
<h4>{headerString}</h4>
|
||||
</div>
|
||||
<div className="stroke metaSidebar showNeverOnMobile" style={{ padding: 0, maxWidth: "300px" }}>
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<h3 style={{ margin: 0, padding: 0 }}>Smart contract prices</h3>
|
||||
</div>
|
||||
<div className="stroke" style={{ margin: 0, padding: 0 }}>
|
||||
<Stat header={"Reward Call"} content1={"$" + redeemRewardCostL2USD + " (vs " + redeemRewardCostL1USD + " on L1)"} />
|
||||
<Stat header={"Claim Ticket"} content1={"$" + claimTicketCostL2USD + " (vs " + claimTicketCostL1USD + " on L1)"} />
|
||||
<Stat header={"Staking Fees"} content1={"$" + stakeFeeCostL2USD + " (vs " + stakeFeeCostL1USD + " on L1)"} />
|
||||
<Stat header={"Change Commission"} content1={"$" + commissionFeeCostL2USD + " (vs " + commissionFeeCostL1USD + " on L1)"} />
|
||||
<Stat header={"Change URI"} content1={"$" + serviceUriFeeCostL2USD + " (vs " + serviceUriFeeCostL1USD + " on L1)"} />
|
||||
</div>
|
||||
<div className='rowAlignRight'>
|
||||
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
|
||||
dispatch(clearOrchestrator());
|
||||
setSearchTerm("");
|
||||
}}>
|
||||
<h4>✖️ Clear</h4>
|
||||
</button>
|
||||
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
|
||||
setShowSidebar(!showSidebar);
|
||||
}}>
|
||||
<h4>🔎 Sidebar</h4>
|
||||
</button>
|
||||
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
|
||||
setShowFilter(!showFilter);
|
||||
}}>
|
||||
<h4>🛠️ Filter</h4>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id='bodyContent'>
|
||||
{sidebar}
|
||||
<div className="mainContent">
|
||||
<EventViewer events={eventsList} searchTerm={searchTerm} setSearchTerm={setSearchTerm} forceVertical={true} showFilter={showFilter} />
|
||||
</div>
|
||||
</div >
|
||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||
<EventViewer events={eventsList} prefill={prefill.get('orchAddr')} />
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
|
@ -3,6 +3,8 @@ import ScrollContainer from "react-indiana-drag-scroll";
|
||||
import Stat from "./statViewer";
|
||||
import ReactTooltip from "react-tooltip";
|
||||
import Address from "./OrchAddressViewer";
|
||||
import OrchDelegatorViewer from "./OrchDelegatorViewer";
|
||||
import OrchInfoViewer from "./OrchInfoViewer";
|
||||
|
||||
function updateClipboard(newClip) {
|
||||
navigator.clipboard.writeText(newClip).then(
|
||||
@ -26,118 +28,71 @@ function copyLink(addr) {
|
||||
}
|
||||
|
||||
const Orchestrator = (obj) => {
|
||||
let rewardCut = 0;
|
||||
let feeCut = 0;
|
||||
let totalStake = 0;
|
||||
let totalVolumeETH = 0;
|
||||
let totalVolumeUSD = 0;
|
||||
let delegators = [];
|
||||
let selfStake = 0;
|
||||
let selfStakeRatio = 0;
|
||||
let thisUrl = "";
|
||||
let thisID = "";
|
||||
if (obj.thisOrchestrator) {
|
||||
if (obj.thisOrchestrator.rewardCut) {
|
||||
rewardCut = (obj.thisOrchestrator.rewardCut / 10000).toFixed(2);
|
||||
}
|
||||
if (obj.thisOrchestrator.feeShare) {
|
||||
feeCut = (100 - (obj.thisOrchestrator.feeShare / 10000)).toFixed(2);
|
||||
}
|
||||
if (obj.thisOrchestrator.totalStake) {
|
||||
totalStake = parseFloat(obj.thisOrchestrator.totalStake).toFixed(2);
|
||||
}
|
||||
if (obj.thisOrchestrator.totalVolumeETH) {
|
||||
totalVolumeETH = parseFloat(obj.thisOrchestrator.totalVolumeETH * 1).toFixed(4);
|
||||
}
|
||||
if (obj.thisOrchestrator.totalVolumeUSD) {
|
||||
totalVolumeUSD = parseFloat(obj.thisOrchestrator.totalVolumeUSD * 1).toFixed(2);
|
||||
}
|
||||
if (obj.thisOrchestrator.delegators && obj.thisOrchestrator.delegator) {
|
||||
delegators = obj.thisOrchestrator.delegators;
|
||||
selfStake = parseFloat(obj.thisOrchestrator.delegator.bondedAmount);
|
||||
selfStakeRatio = ((selfStake / totalStake) * 100).toFixed(2);
|
||||
selfStake = selfStake.toFixed(2);
|
||||
thisID = obj.thisOrchestrator.delegator.id;
|
||||
thisUrl = "https://explorer.livepeer.org/accounts/" + thisID;
|
||||
}
|
||||
|
||||
let shareUrl;
|
||||
if (obj.rootOnly) {
|
||||
shareUrl = window.location.href;
|
||||
} else {
|
||||
let thisFullPath = window.location.href;
|
||||
if (thisFullPath.lastIndexOf("?") > -1) {
|
||||
thisFullPath = thisFullPath.substring(0, thisFullPath.lastIndexOf("?"));
|
||||
}
|
||||
shareUrl = thisFullPath + "?orchAddr=" + thisID;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<div style={{ flexDirection: 'row', display: "flex" }} style={{ marginTop: '1em' }}>
|
||||
<a href={thisUrl}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>Orchestrator Info</h3>
|
||||
<Address address={thisID} />
|
||||
</a>
|
||||
</div>
|
||||
<div className="row" style={{}}>
|
||||
<Stat header={"Earned Fees"} content1={totalVolumeETH + " Eth"} content2={"$" + totalVolumeUSD} />
|
||||
</div>
|
||||
<div className="row" style={{}}>
|
||||
<Stat header={"Commission"} title1={"Reward"} content1={rewardCut + "%"} title2={"Fee"} content2={feeCut + "%"} />
|
||||
</div>
|
||||
<div className="row" style={{}}>
|
||||
<Stat header={"Stake"} title1={"Total"} content1={totalStake + " LPT"} title2={"Self"} content2={selfStake + " LPT (" + selfStakeRatio + ")%"} />
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ display: "flex" }}>
|
||||
<button style={{marginBottom:'1em'}} className="selectOrchLight" data-tip data-for="registerTip" onClick={() => {
|
||||
copyLink(shareUrl);
|
||||
}}>
|
||||
<img alt="" src="clipboard.svg" width="20em" height="20em" />
|
||||
</button>
|
||||
<ReactTooltip id="registerTip" place="top" effect="solid">
|
||||
Copy to clipboard
|
||||
</ReactTooltip>
|
||||
if (obj.forceVertical) {
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="flexContainer" style={{ justifyContent: 'flex-start', alignItems: 'flex-start', flexDirection: 'column' }}>
|
||||
<OrchInfoViewer
|
||||
rewardCut={obj.thisOrchestrator.rewardCut}
|
||||
feeShare={obj.thisOrchestrator.feeShare}
|
||||
totalStake={obj.thisOrchestrator.totalStake}
|
||||
totalVolumeETH={obj.thisOrchestrator.totalVolumeETH}
|
||||
totalVolumeUSD={obj.thisOrchestrator.totalVolumeUSD}
|
||||
delegator={obj.thisOrchestrator.delegator}
|
||||
/>
|
||||
<OrchDelegatorViewer delegators={obj.thisOrchestrator.delegators} forceVertical={obj.forceVertical} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ alignItems: 'stretch', flex: 2, marginLeft: '1em', borderLeft: '3px solid rgba(15,15,15,0.05)' }}>
|
||||
<div className="row" style={{ marginTop: '1em' }}>
|
||||
<h3 style={{ padding: 0, margin: 0 }}>{delegators.length} Current Delegators</h3>
|
||||
)
|
||||
}else{
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="flexContainer" style={{ justifyContent: 'flex-start', alignItems: 'flex-start' }}>
|
||||
<OrchInfoViewer
|
||||
rewardCut={obj.thisOrchestrator.rewardCut}
|
||||
feeShare={obj.thisOrchestrator.feeShare}
|
||||
totalStake={obj.thisOrchestrator.totalStake}
|
||||
totalVolumeETH={obj.thisOrchestrator.totalVolumeETH}
|
||||
totalVolumeUSD={obj.thisOrchestrator.totalVolumeUSD}
|
||||
delegator={obj.thisOrchestrator.delegator}
|
||||
/>
|
||||
<OrchDelegatorViewer delegators={obj.thisOrchestrator.delegators} forceVertical={obj.forceVertical} />
|
||||
</div>
|
||||
<div className="content-wrapper">
|
||||
<ScrollContainer className="overflow-container" hideScrollbars={false}>
|
||||
<div className="overflow-content" style={{ cursor: 'grab' }}>
|
||||
{
|
||||
delegators.map((delObj, idx) => {
|
||||
return (
|
||||
<div className="rowAlignLeft" key={"delegator" + idx} style={{ marginLeft: '1em', borderBottom: '2px solid rgba(15,15,15,0.05)' }}>
|
||||
<Address address={delObj.id} seed={"delegator" + idx + delObj.id} />
|
||||
<div className="rowAlignRight">
|
||||
<p className="darkText">{parseFloat(delObj.bondedAmount).toFixed(2)} LPT since round {delObj.startRound}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
</div>
|
||||
</ScrollContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
if (obj.forceVertical) {
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="flexContainer" style={{ alignItems: 'center', flexDirection: 'column' }}>
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||
<h3>Orchestrator Info</h3>
|
||||
</div>
|
||||
<div className="rowAlignLeft">
|
||||
<p>Inspect an Orchestrator by clicking on their address</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="flexContainer" style={{ alignItems: 'center' }}>
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||
<h3>Orchestrator Info</h3>
|
||||
</div>
|
||||
<div className="rowAlignLeft">
|
||||
<p>Inspect an Orchestrator by clicking on their address</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="hostInfo">
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||
<h3>Orchestrator Info</h3>
|
||||
</div>
|
||||
<div className="rowAlignLeft">
|
||||
<p>Click on an orchestrator address in the list below!</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default Orchestrator;
|
@ -3,7 +3,8 @@ import {
|
||||
RECEIVE_BLOCKCHAIN_DATA,
|
||||
RECEIVE_EVENTS,
|
||||
RECEIVE_ORCHESTRATOR,
|
||||
RECEIVE_CURRENT_ORCHESTRATOR
|
||||
RECEIVE_CURRENT_ORCHESTRATOR,
|
||||
CLEAR_ORCHESTRATOR
|
||||
} from "../../actions/livepeer";
|
||||
|
||||
export default (state = {}, { type, message }) => {
|
||||
@ -19,6 +20,8 @@ export default (state = {}, { type, message }) => {
|
||||
return { ...state, thisOrchestrator: message };
|
||||
case RECEIVE_ORCHESTRATOR:
|
||||
return { ...state, selectedOrchestrator: message };
|
||||
case CLEAR_ORCHESTRATOR:
|
||||
return { ...state, selectedOrchestrator: null };
|
||||
default:
|
||||
return { ...state };
|
||||
}
|
||||
|
@ -15,16 +15,16 @@ const Stat = (obj) => {
|
||||
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h3 style={{ margin: 0, padding: 0 }}>{obj.header}</h3>
|
||||
</div>
|
||||
<div className="row" style={{}}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<div className="row" style={{ margin: 0 }}>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h4 style={{ margin: 0, padding: 0 }}>{obj.title1}</h4>
|
||||
<div className="rowAlignLeft" style={{ margin: 0, marginLeft: '1em', padding: 0 }}>
|
||||
<p className="darkText">{obj.content1}</p>
|
||||
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<p className="darkText">{obj.content1}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<h4 style={{ margin: 0, padding: 0 }}>{obj.title2}</h4>
|
||||
<div className="rowAlignLeft" style={{ margin: 0, marginLeft: '1em', padding: 0 }}>
|
||||
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
||||
<p className="darkText">{obj.content2}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -140,10 +140,36 @@ svg {
|
||||
from { top: 0; } to { top: calc(100vh - 69px); }
|
||||
}
|
||||
|
||||
.metaSidebar {
|
||||
|
||||
#header {
|
||||
height: 50px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
background-color: rgba(180, 175, 252, 0.80);
|
||||
}
|
||||
#bodyContent {
|
||||
height: calc( 100vh - 50px);
|
||||
max-height: calc( 100vh - 50px);
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
#sideContent {
|
||||
background-color: rgba(180, 175, 252, 0.80);
|
||||
backdrop-filter: blur(6px);
|
||||
box-shadow: 9px 13px 8px 8px rgba(8, 7, 56, 0.692);
|
||||
border-bottom-right-radius: 1em;
|
||||
width: 400px;
|
||||
}
|
||||
.mainContent {
|
||||
overflow: hidden;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
flex-basis: 0;
|
||||
flex-grow: 999;
|
||||
}
|
||||
|
||||
|
||||
.fullGrafana {
|
||||
width: 100%;
|
||||
@ -194,6 +220,10 @@ svg {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.forceWrap{
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stroke {
|
||||
box-sizing: border-box;
|
||||
padding-bottom: 20px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user