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');
|
const [thisDate, thisTime] = dateObj.toISOString().split('T');
|
||||||
return (
|
return (
|
||||||
<div className="rowAlignLeft" style={{ width: '100%', marginTop: '1em' }}>
|
<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">
|
<span className="rowAlignRight elipsText">
|
||||||
<a className="selectOrch" href={"https://arbiscan.io/block/" + obj.block}>
|
<a className="selectOrch" href={"https://arbiscan.io/block/" + obj.block}>
|
||||||
🔗{obj.block}
|
🔗{obj.block}
|
||||||
|
@ -3,9 +3,9 @@ import ReactTooltip from "react-tooltip";
|
|||||||
|
|
||||||
const Address = (obj) => {
|
const Address = (obj) => {
|
||||||
return (
|
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} >
|
<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" />
|
<img alt="" src="livepeer.png" width="20" height="20" />
|
||||||
<span className="elipsText">{obj.address}</span>
|
<span className="elipsText">{obj.address}</span>
|
||||||
</div>
|
</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_EVENTS = "RECEIVE_EVENTS";
|
||||||
export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR";
|
export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR";
|
||||||
export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR";
|
export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR";
|
||||||
|
export const CLEAR_ORCHESTRATOR = "CLEAR_ORCHESTRATOR";
|
||||||
|
|
||||||
const setQuotes = message => ({
|
const setQuotes = message => ({
|
||||||
type: RECEIVE_QUOTES, message
|
type: RECEIVE_QUOTES, message
|
||||||
@ -33,6 +34,9 @@ const setCurrentOrchestratorInfo = message => ({
|
|||||||
const setOrchestratorInfo = message => ({
|
const setOrchestratorInfo = message => ({
|
||||||
type: RECEIVE_ORCHESTRATOR, message
|
type: RECEIVE_ORCHESTRATOR, message
|
||||||
});
|
});
|
||||||
|
const clearOrchestratorInfo = () => ({
|
||||||
|
type: CLEAR_ORCHESTRATOR
|
||||||
|
})
|
||||||
|
|
||||||
export const getQuotes = () => async dispatch => {
|
export const getQuotes = () => async dispatch => {
|
||||||
const response = await apiUtil.getQuotes();
|
const response = await apiUtil.getQuotes();
|
||||||
@ -127,7 +131,7 @@ export const getEvents = () => async dispatch => {
|
|||||||
else if (eventContainsRebond) {
|
else if (eventContainsRebond) {
|
||||||
eventType = "Stake";
|
eventType = "Stake";
|
||||||
eventColour = stakeColour;
|
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
|
// 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";
|
eventDescription = "staked " + tmpAmount.toFixed(2) + " LPT";
|
||||||
} else if (eventFrom === eventTo) {
|
} else if (eventFrom === eventTo) {
|
||||||
eventFrom = "";
|
eventFrom = "";
|
||||||
eventDescription = "increased their stake to " + tmpAmount.toFixed(2) + " LPT";
|
eventDescription = "is now staking " + tmpAmount.toFixed(2) + " LPT";
|
||||||
} else {
|
} else {
|
||||||
eventDescription = "moved a " + tmpAmount.toFixed(2) + " LPT stake";
|
eventDescription = "moved a " + tmpAmount.toFixed(2) + " LPT stake";
|
||||||
}
|
}
|
||||||
@ -370,3 +374,7 @@ export const getOrchestratorInfo = (orchAddr) => async dispatch => {
|
|||||||
}
|
}
|
||||||
return dispatch(receiveErrors(data));
|
return dispatch(receiveErrors(data));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const clearOrchestrator = () => async dispatch => {
|
||||||
|
return dispatch(clearOrchestratorInfo({}));
|
||||||
|
};
|
@ -10,7 +10,7 @@ import Block from "./BlockViewer";
|
|||||||
const EventButton = (obj) => {
|
const EventButton = (obj) => {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
let eventArrow;
|
|
||||||
let eventTo;
|
let eventTo;
|
||||||
let eventFrom;
|
let eventFrom;
|
||||||
let eventCaller;
|
let eventCaller;
|
||||||
@ -21,13 +21,14 @@ const EventButton = (obj) => {
|
|||||||
if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") {
|
if (obj.eventObj.eventTo === "0x0000000000000000000000000000000000000000") {
|
||||||
obj.eventObj.eventTo = "";
|
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 || obj.eventObj.eventFrom || obj.eventObj.eventCaller) {
|
||||||
if (obj.eventObj.eventTo) {
|
if (obj.eventObj.eventTo) {
|
||||||
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) }} >
|
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventTo) }} >
|
||||||
<span className="elipsText">🔎</span>
|
<span className="elipsText">🔎</span>
|
||||||
</button>
|
</button>
|
||||||
@ -38,7 +39,11 @@ const EventButton = (obj) => {
|
|||||||
}
|
}
|
||||||
if (obj.eventObj.eventFrom) {
|
if (obj.eventObj.eventFrom) {
|
||||||
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) }} >
|
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventFrom) }} >
|
||||||
<span className="elipsText">🔎</span>
|
<span className="elipsText">🔎</span>
|
||||||
</button>
|
</button>
|
||||||
@ -49,7 +54,11 @@ const EventButton = (obj) => {
|
|||||||
}
|
}
|
||||||
if (obj.eventObj.eventCaller) {
|
if (obj.eventObj.eventCaller) {
|
||||||
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) }} >
|
<button className="selectOrch" style={{ margin: 0, padding: '0.5em' }} onClick={() => { obj.setSearchTerm(obj.eventObj.eventCaller) }} >
|
||||||
<span className="elipsText">🔎</span>
|
<span className="elipsText">🔎</span>
|
||||||
</button>
|
</button>
|
||||||
@ -58,40 +67,29 @@ const EventButton = (obj) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
eventRightAddr = <div className="rowAlignRight" style={{ width: 'unset', padding: 0, margin: 0 }}>
|
eventRightAddr = <div className="strokeSmollLeft" style={{ width: 'unset', padding: 0, margin: 0 }}>
|
||||||
{eventFrom}
|
|
||||||
{eventArrow}
|
|
||||||
{eventTo}
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
let blockNumber;
|
let blockNumber;
|
||||||
if (obj.isFirstOfBlock) {
|
if (obj.isFirstOfBlock) {
|
||||||
blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} />
|
blockNumber = <Block block={obj.isFirstOfBlock} time={obj.time} url={obj.eventObj.transactionUrl} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="stroke" style={{ width: '100%', padding: 0, margin: 0 }}>
|
<div className="stroke" style={{ width: '100%', padding: 0, margin: 0 }}>
|
||||||
{blockNumber}
|
{blockNumber}
|
||||||
<div className="rowAlignLeft" style={{ backgroundColor: obj.eventObj.eventColour, borderRadius: "1.2em", width: '100%' }}>
|
<div className="rowAlignLeft" style={{ borderRadius: "1.2em", backgroundColor: obj.eventObj.eventColour, padding: 0, margin: 0 }}>
|
||||||
<div className="rowAlignLeft" style={{ flex: '1', width: 'unset' }}>
|
<div className="strokeSmollLeft">
|
||||||
<a className="selectOrch" href={obj.eventObj.transactionUrl}>
|
{eventCaller}
|
||||||
<img alt="" src="arb.svg" width="30" height="30" />
|
<p className="rowAlignLeft withWrap" style={{ width: '100%' }}>
|
||||||
</a>
|
💬 {obj.eventObj.eventDescription}
|
||||||
<a className="selectOrch" href={"https://explorer.livepeer.org/accounts/" + obj.eventObj.eventCaller}>
|
</p>
|
||||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
{eventFrom}
|
||||||
</a>
|
{eventTo}
|
||||||
<div className="rowAlignLeft" style={{ flex: '1', width: '100%', padding: 0, margin: 0 }}>
|
|
||||||
{eventCaller}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="rowAlignLeft" style={{ flex: '2', width: 'unset', padding: 0, margin: 0 }}>
|
</div>
|
||||||
<span className="rowAlignLeft elipsText">
|
|
||||||
{obj.eventObj.eventDescription}
|
|
||||||
</span>
|
|
||||||
{eventRightAddr}
|
|
||||||
</div>
|
|
||||||
</div >
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ const defaultMaxShown = 100;
|
|||||||
const defaultIncrementMaxShown = 100;
|
const defaultIncrementMaxShown = 100;
|
||||||
|
|
||||||
const EventViewer = (obj) => {
|
const EventViewer = (obj) => {
|
||||||
const [searchTerm, setSearchTerm] = useState(obj.prefill || "");
|
|
||||||
const [amountFilter, setAmountFilter] = useState("0");
|
const [amountFilter, setAmountFilter] = useState("0");
|
||||||
const [maxAmount, setMaxAmount] = useState(defaultMaxShown);
|
const [maxAmount, setMaxAmount] = useState(defaultMaxShown);
|
||||||
const [filterActivated, setFilterActivated] = useState(true);
|
const [filterActivated, setFilterActivated] = useState(true);
|
||||||
@ -49,35 +48,29 @@ const EventViewer = (obj) => {
|
|||||||
let prevBlock = 0;
|
let prevBlock = 0;
|
||||||
let showMoreBlock;
|
let showMoreBlock;
|
||||||
if (maxAmount < limitShown) {
|
if (maxAmount < limitShown) {
|
||||||
showMoreBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
showMoreBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||||
<h3></h3>
|
setMaxAmount(maxAmount + defaultIncrementMaxShown);
|
||||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
}}>
|
||||||
setMaxAmount(maxAmount + defaultIncrementMaxShown);
|
<h3>Show more</h3>
|
||||||
}}>
|
</button>
|
||||||
<h3>Show more</h3>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
}
|
}
|
||||||
let showLessBlock;
|
let showLessBlock;
|
||||||
if (defaultMaxShown < maxAmount) {
|
if (defaultMaxShown < maxAmount) {
|
||||||
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
showLessBlock = <button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||||
<h3></h3>
|
setMaxAmount(defaultMaxShown);
|
||||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
}}>
|
||||||
setMaxAmount(defaultMaxShown);
|
<h3>Show {defaultMaxShown}</h3>
|
||||||
}}>
|
</button>
|
||||||
<h3>Show {defaultMaxShown}</h3>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
} else {
|
} else {
|
||||||
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '5em' }}></div>
|
showLessBlock = <div className="strokeSmollLeft" style={{ margin: 0, padding: 0, width: '5em' }}></div>
|
||||||
}
|
}
|
||||||
|
|
||||||
let searchTermText;
|
let searchTermText;
|
||||||
if (searchTerm !== "") {
|
if (obj.searchTerm !== "") {
|
||||||
if (searchTerm.length > 15) {
|
if (obj.searchTerm.length > 15) {
|
||||||
searchTermText = <h3>Only showing addresses containing {searchTerm.substring(0, 15)}...</h3>
|
searchTermText = <h3>Only showing addresses containing {obj.searchTerm.substring(0, 15)}...</h3>
|
||||||
} else {
|
} else {
|
||||||
searchTermText = <h3>Only showing addresses containing {searchTerm}</h3>
|
searchTermText = <h3>Only showing addresses containing {obj.searchTerm}</h3>
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
searchTermText = <h3>Filter by Orchestrator address</h3>
|
searchTermText = <h3>Filter by Orchestrator address</h3>
|
||||||
@ -95,11 +88,11 @@ const EventViewer = (obj) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Filter name on from, to, caller
|
// Filter name on from, to, caller
|
||||||
if (searchTerm !== "") {
|
if (obj.searchTerm !== "") {
|
||||||
let isFiltered = true;
|
let isFiltered = true;
|
||||||
if (eventObj.eventCaller.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
if (eventObj.eventCaller.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||||
if (eventObj.eventFrom.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
if (eventObj.eventFrom.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||||
if (eventObj.eventTo.toLowerCase().includes(searchTerm.toLowerCase())) isFiltered = false;
|
if (eventObj.eventTo.toLowerCase().includes(obj.searchTerm.toLowerCase())) isFiltered = false;
|
||||||
if (isFiltered) continue;
|
if (isFiltered) continue;
|
||||||
}
|
}
|
||||||
// Filter Events on filter buttons
|
// Filter Events on filter buttons
|
||||||
@ -164,7 +157,7 @@ const EventViewer = (obj) => {
|
|||||||
eventList.push(<EventButton
|
eventList.push(<EventButton
|
||||||
key={eventObj.transactionHash + unfiltered}
|
key={eventObj.transactionHash + unfiltered}
|
||||||
eventObj={eventObj}
|
eventObj={eventObj}
|
||||||
setSearchTerm={setSearchTerm}
|
setSearchTerm={obj.setSearchTerm}
|
||||||
/>);
|
/>);
|
||||||
} else {
|
} else {
|
||||||
prevBlock = eventObj.transactionBlock;
|
prevBlock = eventObj.transactionBlock;
|
||||||
@ -173,81 +166,69 @@ const EventViewer = (obj) => {
|
|||||||
eventObj={eventObj}
|
eventObj={eventObj}
|
||||||
isFirstOfBlock={prevBlock}
|
isFirstOfBlock={prevBlock}
|
||||||
time={eventObj.transactionTime}
|
time={eventObj.transactionTime}
|
||||||
setSearchTerm={setSearchTerm}
|
setSearchTerm={obj.setSearchTerm}
|
||||||
/>);
|
/>);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
let filterBit;
|
||||||
<div className="stroke roundedOpaque" style={{ padding: 0, margin: 0, marginTop: '2em', position: 'absolute', bottom: 0, top: '300px', overflowY: 'auto', overflowX: 'hidden', width: 'unset' }}>
|
if (obj.showFilter) {
|
||||||
<div className="row showNeverOnMobile">
|
filterBit = <div className="row roundedOpaque" style={{ borderTopLeftRadius: 0, borderTopRightRadius: 0, borderBottomLeftRadius: 0, margin: 0 }}>
|
||||||
<div className="row">
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0, flex: 1 }}>
|
||||||
{showLessBlock}
|
<div className="stroke" style={{ margin: "0", padding: 0 }}>
|
||||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<h3>Showing max {maxAmount} results</h3>
|
<h3>Showing max {maxAmount} results</h3>
|
||||||
</div>
|
</div>
|
||||||
{showMoreBlock}
|
<div className="row" style={{ margin: 0, padding: 0 }}>
|
||||||
</div>
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<div className="row">
|
{showLessBlock}
|
||||||
<div className="stroke" style={{ margin: "0", padding: 0 }}>
|
</div>
|
||||||
{searchTermText}
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<input className="searchField" style={{ width: '100%' }}
|
{showMoreBlock}
|
||||||
value={searchTerm}
|
</div>
|
||||||
onChange={(evt) => setSearchTerm(evt.target.value)}
|
|
||||||
placeholder='Filter by Orchestrator address'
|
|
||||||
type="text"
|
|
||||||
/>
|
|
||||||
</div>
|
</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 }}>
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<h3></h3>
|
|
||||||
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||||
const curVal = parseFloat(amountFilter);
|
setAmountFilter(0);
|
||||||
setAmountFilter(curVal - 1000);
|
|
||||||
}}>
|
}}>
|
||||||
<h3>-1000</h3>
|
<h3>0</h3>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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 }}>
|
<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={() => {
|
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '4em' }} onClick={() => {
|
||||||
const curVal = parseFloat(amountFilter);
|
const curVal = parseFloat(amountFilter);
|
||||||
setAmountFilter(curVal + 100);
|
setAmountFilter(curVal + 100);
|
||||||
@ -256,7 +237,6 @@ const EventViewer = (obj) => {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="strokeSmollLeft" 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={() => {
|
<button className={"nonHomeButton"} style={{ backgroundColor: greyColour, margin: 0, padding: '0', width: '5em' }} onClick={() => {
|
||||||
const curVal = parseFloat(amountFilter);
|
const curVal = parseFloat(amountFilter);
|
||||||
setAmountFilter(curVal + 1000);
|
setAmountFilter(curVal + 1000);
|
||||||
@ -266,48 +246,60 @@ const EventViewer = (obj) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="content-wrapper" style={{ alignItems: 'stretch', width: '100%' }}>
|
</div>
|
||||||
<ScrollContainer className="overflow-container" hideScrollbars={false} style={{}}>
|
}
|
||||||
<div className="overflow-content" style={{ cursor: 'grab', paddingTop: 0}}>
|
|
||||||
{eventList}
|
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>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,7 +44,7 @@ const Grafana = (obj) => {
|
|||||||
<div className="flexContainer">
|
<div className="flexContainer">
|
||||||
<div className="stroke" style={{ marginTop: 0, marginBottom: 5, paddingBottom: 0 }}>
|
<div className="stroke" style={{ marginTop: 0, marginBottom: 5, paddingBottom: 0 }}>
|
||||||
<div className="stroke roundedOpaque" style={{}}>
|
<div className="stroke roundedOpaque" style={{}}>
|
||||||
<div className="row">
|
<div className="flexContainer" style={{ margin: 0, textAlign: 'center',alignItems: 'center', justifyContent:'center' }}>
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<img alt="" src="livepeer.png" width="30" height="30" />
|
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||||
<p>${lptPrice}</p>
|
<p>${lptPrice}</p>
|
||||||
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from 'react'
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
import { Navigate, useSearchParams } from "react-router-dom";
|
import { Navigate, useSearchParams } from "react-router-dom";
|
||||||
import { useSelector, useDispatch } from 'react-redux'
|
import { useSelector, useDispatch } from 'react-redux'
|
||||||
import { getOrchestratorInfo } from "./actions/livepeer";
|
import { getOrchestratorInfo, clearOrchestrator } from "./actions/livepeer";
|
||||||
import EventViewer from "./eventViewer";
|
import EventViewer from "./eventViewer";
|
||||||
import Orchestrator from "./orchestratorViewer";
|
import Orchestrator from "./orchestratorViewer";
|
||||||
import Stat from "./statViewer";
|
import Stat from "./statViewer";
|
||||||
@ -11,14 +11,18 @@ import Stat from "./statViewer";
|
|||||||
|
|
||||||
const Livepeer = (obj) => {
|
const Livepeer = (obj) => {
|
||||||
const [prefill, setPrefill] = useSearchParams();
|
const [prefill, setPrefill] = useSearchParams();
|
||||||
|
const [searchTerm, setSearchTerm] = useState("");
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const livepeer = useSelector((state) => state.livepeerstate);
|
const livepeer = useSelector((state) => state.livepeerstate);
|
||||||
const [redirectToHome, setRedirectToHome] = useState(false);
|
const [redirectToHome, setRedirectToHome] = useState(false);
|
||||||
|
const [showFilter, setShowFilter] = useState(false);
|
||||||
|
const [showSidebar, setShowSidebar] = useState(true);
|
||||||
console.log("Rendering Livepeer");
|
console.log("Rendering Livepeer");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (prefill.get('orchAddr') && prefill.get('orchAddr') !== "") {
|
if (prefill.get('orchAddr') && prefill.get('orchAddr') !== "") {
|
||||||
dispatch(getOrchestratorInfo(prefill.get('orchAddr')));
|
dispatch(getOrchestratorInfo(prefill.get('orchAddr')));
|
||||||
|
setSearchTerm(prefill.get('orchAddr'));
|
||||||
}
|
}
|
||||||
}, [prefill]);
|
}, [prefill]);
|
||||||
|
|
||||||
@ -123,36 +127,72 @@ const Livepeer = (obj) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let thisOrchObj;
|
let thisOrchObj;
|
||||||
|
let headerString;
|
||||||
if (livepeer.selectedOrchestrator) {
|
if (livepeer.selectedOrchestrator) {
|
||||||
thisOrchObj = 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 (
|
return (
|
||||||
<div style={{ width: '100%', height: '100%' }}>
|
<div style={{ margin: 0, padding: 0, height: '100%', width: '100%', overflow: 'hidden' }}>
|
||||||
<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' }}>
|
<div id='header'>
|
||||||
<button className="homeButton" onClick={() => {
|
<div className='rowAlignLeft'>
|
||||||
setRedirectToHome(true);
|
<button className="homeButton" onClick={() => {
|
||||||
}}>
|
setRedirectToHome(true);
|
||||||
<img alt="" src="livepeer.png" width="100em" height="100em" />
|
}}>
|
||||||
</button>
|
<h1 style={{margin: 0, padding: 0}}>🏠</h1>
|
||||||
<div className="row" style={{ alignItems: 'stretch', height: '100%', flex: 2, padding: '0.2em', maxWidth: "1100px" }}>
|
</button>
|
||||||
<Orchestrator thisOrchestrator={thisOrchObj} rootOnly={false} />
|
<h4>{headerString}</h4>
|
||||||
</div>
|
</div>
|
||||||
<div className="stroke metaSidebar showNeverOnMobile" style={{ padding: 0, maxWidth: "300px" }}>
|
<div className='rowAlignRight'>
|
||||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
|
||||||
<h3 style={{ margin: 0, padding: 0 }}>Smart contract prices</h3>
|
dispatch(clearOrchestrator());
|
||||||
</div>
|
setSearchTerm("");
|
||||||
<div className="stroke" style={{ margin: 0, padding: 0 }}>
|
}}>
|
||||||
<Stat header={"Reward Call"} content1={"$" + redeemRewardCostL2USD + " (vs " + redeemRewardCostL1USD + " on L1)"} />
|
<h4>✖️ Clear</h4>
|
||||||
<Stat header={"Claim Ticket"} content1={"$" + claimTicketCostL2USD + " (vs " + claimTicketCostL1USD + " on L1)"} />
|
</button>
|
||||||
<Stat header={"Staking Fees"} content1={"$" + stakeFeeCostL2USD + " (vs " + stakeFeeCostL1USD + " on L1)"} />
|
<button className="homeButton" style={{padding: 0, paddingRight: '1em', paddingLeft: '1em'}} onClick={() => {
|
||||||
<Stat header={"Change Commission"} content1={"$" + commissionFeeCostL2USD + " (vs " + commissionFeeCostL1USD + " on L1)"} />
|
setShowSidebar(!showSidebar);
|
||||||
<Stat header={"Change URI"} content1={"$" + serviceUriFeeCostL2USD + " (vs " + serviceUriFeeCostL1USD + " on L1)"} />
|
}}>
|
||||||
</div>
|
<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 >
|
|
||||||
<div className="row" style={{ margin: 0, padding: 0 }}>
|
|
||||||
<EventViewer events={eventsList} prefill={prefill.get('orchAddr')} />
|
|
||||||
</div>
|
</div>
|
||||||
</div >
|
</div >
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,8 @@ import ScrollContainer from "react-indiana-drag-scroll";
|
|||||||
import Stat from "./statViewer";
|
import Stat from "./statViewer";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
import Address from "./OrchAddressViewer";
|
import Address from "./OrchAddressViewer";
|
||||||
|
import OrchDelegatorViewer from "./OrchDelegatorViewer";
|
||||||
|
import OrchInfoViewer from "./OrchInfoViewer";
|
||||||
|
|
||||||
function updateClipboard(newClip) {
|
function updateClipboard(newClip) {
|
||||||
navigator.clipboard.writeText(newClip).then(
|
navigator.clipboard.writeText(newClip).then(
|
||||||
@ -26,118 +28,71 @@ function copyLink(addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Orchestrator = (obj) => {
|
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) {
|
||||||
if (obj.thisOrchestrator.rewardCut) {
|
if (obj.forceVertical) {
|
||||||
rewardCut = (obj.thisOrchestrator.rewardCut / 10000).toFixed(2);
|
return (
|
||||||
}
|
<div className="hostInfo">
|
||||||
if (obj.thisOrchestrator.feeShare) {
|
<div className="flexContainer" style={{ justifyContent: 'flex-start', alignItems: 'flex-start', flexDirection: 'column' }}>
|
||||||
feeCut = (100 - (obj.thisOrchestrator.feeShare / 10000)).toFixed(2);
|
<OrchInfoViewer
|
||||||
}
|
rewardCut={obj.thisOrchestrator.rewardCut}
|
||||||
if (obj.thisOrchestrator.totalStake) {
|
feeShare={obj.thisOrchestrator.feeShare}
|
||||||
totalStake = parseFloat(obj.thisOrchestrator.totalStake).toFixed(2);
|
totalStake={obj.thisOrchestrator.totalStake}
|
||||||
}
|
totalVolumeETH={obj.thisOrchestrator.totalVolumeETH}
|
||||||
if (obj.thisOrchestrator.totalVolumeETH) {
|
totalVolumeUSD={obj.thisOrchestrator.totalVolumeUSD}
|
||||||
totalVolumeETH = parseFloat(obj.thisOrchestrator.totalVolumeETH * 1).toFixed(4);
|
delegator={obj.thisOrchestrator.delegator}
|
||||||
}
|
/>
|
||||||
if (obj.thisOrchestrator.totalVolumeUSD) {
|
<OrchDelegatorViewer delegators={obj.thisOrchestrator.delegators} forceVertical={obj.forceVertical} />
|
||||||
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>
|
|
||||||
</div>
|
</div>
|
||||||
</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' }}>
|
}else{
|
||||||
<h3 style={{ padding: 0, margin: 0 }}>{delegators.length} Current Delegators</h3>
|
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>
|
||||||
<div className="content-wrapper">
|
</div>
|
||||||
<ScrollContainer className="overflow-container" hideScrollbars={false}>
|
)
|
||||||
<div className="overflow-content" style={{ cursor: 'grab' }}>
|
}
|
||||||
{
|
}
|
||||||
delegators.map((delObj, idx) => {
|
if (obj.forceVertical) {
|
||||||
return (
|
return (
|
||||||
<div className="rowAlignLeft" key={"delegator" + idx} style={{ marginLeft: '1em', borderBottom: '2px solid rgba(15,15,15,0.05)' }}>
|
<div className="hostInfo">
|
||||||
<Address address={delObj.id} seed={"delegator" + idx + delObj.id} />
|
<div className="flexContainer" style={{ alignItems: 'center', flexDirection: 'column' }}>
|
||||||
<div className="rowAlignRight">
|
<div className="rowAlignLeft">
|
||||||
<p className="darkText">{parseFloat(delObj.bondedAmount).toFixed(2)} LPT since round {delObj.startRound}</p>
|
<img alt="" src="livepeer.png" width="30" height="30" />
|
||||||
</div>
|
<h3>Orchestrator Info</h3>
|
||||||
</div>
|
</div>
|
||||||
)
|
<div className="rowAlignLeft">
|
||||||
})
|
<p>Inspect an Orchestrator by clicking on their address</p>
|
||||||
}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ScrollContainer>
|
</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>
|
</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;
|
export default Orchestrator;
|
@ -3,7 +3,8 @@ import {
|
|||||||
RECEIVE_BLOCKCHAIN_DATA,
|
RECEIVE_BLOCKCHAIN_DATA,
|
||||||
RECEIVE_EVENTS,
|
RECEIVE_EVENTS,
|
||||||
RECEIVE_ORCHESTRATOR,
|
RECEIVE_ORCHESTRATOR,
|
||||||
RECEIVE_CURRENT_ORCHESTRATOR
|
RECEIVE_CURRENT_ORCHESTRATOR,
|
||||||
|
CLEAR_ORCHESTRATOR
|
||||||
} from "../../actions/livepeer";
|
} from "../../actions/livepeer";
|
||||||
|
|
||||||
export default (state = {}, { type, message }) => {
|
export default (state = {}, { type, message }) => {
|
||||||
@ -19,6 +20,8 @@ export default (state = {}, { type, message }) => {
|
|||||||
return { ...state, thisOrchestrator: message };
|
return { ...state, thisOrchestrator: message };
|
||||||
case RECEIVE_ORCHESTRATOR:
|
case RECEIVE_ORCHESTRATOR:
|
||||||
return { ...state, selectedOrchestrator: message };
|
return { ...state, selectedOrchestrator: message };
|
||||||
|
case CLEAR_ORCHESTRATOR:
|
||||||
|
return { ...state, selectedOrchestrator: null };
|
||||||
default:
|
default:
|
||||||
return { ...state };
|
return { ...state };
|
||||||
}
|
}
|
||||||
|
@ -15,16 +15,16 @@ const Stat = (obj) => {
|
|||||||
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<h3 style={{ margin: 0, padding: 0 }}>{obj.header}</h3>
|
<h3 style={{ margin: 0, padding: 0 }}>{obj.header}</h3>
|
||||||
</div>
|
</div>
|
||||||
<div className="row" style={{}}>
|
<div className="row" style={{ margin: 0 }}>
|
||||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<h4 style={{ margin: 0, padding: 0 }}>{obj.title1}</h4>
|
<h4 style={{ margin: 0, padding: 0 }}>{obj.title1}</h4>
|
||||||
<div className="rowAlignLeft" style={{ margin: 0, marginLeft: '1em', padding: 0 }}>
|
<div className="rowAlignLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<p className="darkText">{obj.content1}</p>
|
<p className="darkText">{obj.content1}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
<div className="strokeSmollLeft" style={{ margin: 0, padding: 0 }}>
|
||||||
<h4 style={{ margin: 0, padding: 0 }}>{obj.title2}</h4>
|
<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>
|
<p className="darkText">{obj.content2}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -140,10 +140,36 @@ svg {
|
|||||||
from { top: 0; } to { top: calc(100vh - 69px); }
|
from { top: 0; } to { top: calc(100vh - 69px); }
|
||||||
}
|
}
|
||||||
|
|
||||||
.metaSidebar {
|
|
||||||
|
#header {
|
||||||
|
height: 50px;
|
||||||
display: flex;
|
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 {
|
.fullGrafana {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -194,6 +220,10 @@ svg {
|
|||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.forceWrap{
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
.stroke {
|
.stroke {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user