mirror of
https://github.com/stronk-dev/LivepeerEvents.git
synced 2025-07-05 10:45:10 +02:00
ENS support and other stuff
This commit is contained in:
parent
8dc1d2b2c0
commit
114147cdcd
@ -20,6 +20,7 @@
|
||||
"connect-mongo": "^3.1.2",
|
||||
"crypto-js": "^3.1.9-1",
|
||||
"esm": "^3.2.20",
|
||||
"ethers": "^5.6.1",
|
||||
"express": "^4.17.1",
|
||||
"express-session": "^1.17.0",
|
||||
"graphql-request": "^4.0.0",
|
||||
|
@ -1,4 +1,3 @@
|
||||
//Server configuration variables
|
||||
export const {
|
||||
NODE_PORT = 42609,
|
||||
NODE_ENV = 'local',
|
||||
@ -17,7 +16,10 @@ export const {
|
||||
CONF_TIMEOUT_CMC = 360000,
|
||||
CONF_TIMEOUT_ALCHEMY = 2000,
|
||||
CONF_TIMEOUT_LIVEPEER = 60000,
|
||||
CONF_TIMEOUT_ENS_DOMAIN = 86400000,
|
||||
CONF_TIMEOUT_ENS_INFO = 3600000,
|
||||
CONF_DISABLE_SYNC = false,
|
||||
CONF_DISABLE_DB = false,
|
||||
CONF_DISABLE_CMC = false
|
||||
CONF_DISABLE_CMC = false,
|
||||
CONF_DISABLE_ENS = false
|
||||
} = process.env;
|
||||
|
@ -8,9 +8,10 @@ import {
|
||||
API_CMC, API_L1_HTTP, API_L2_HTTP, API_L2_WS,
|
||||
CONF_DEFAULT_ORCH, CONF_SIMPLE_MODE, CONF_TIMEOUT_CMC,
|
||||
CONF_TIMEOUT_ALCHEMY, CONF_TIMEOUT_LIVEPEER, CONF_DISABLE_SYNC,
|
||||
CONF_DISABLE_DB,
|
||||
CONF_DISABLE_CMC
|
||||
CONF_DISABLE_DB, CONF_DISABLE_CMC, CONF_TIMEOUT_ENS_DOMAIN,
|
||||
CONF_TIMEOUT_ENS_INFO, CONF_DISABLE_ENS
|
||||
} from "../config";
|
||||
|
||||
// Do API requests to other API's
|
||||
const https = require('https');
|
||||
// Read ABI files
|
||||
@ -45,8 +46,14 @@ if (!CONF_SIMPLE_MODE) {
|
||||
}
|
||||
// For listening to blockchain events
|
||||
|
||||
// ENS stuff TODO: CONF_DISABLE_ENS
|
||||
const { ethers } = require("ethers");
|
||||
const provider = new ethers.providers.JsonRpcProvider(API_L1_HTTP);
|
||||
// const ens = new ENS({ provider: web3layer1, ensAddress: getEnsAddress('1') });
|
||||
let ensDomainCache = [];
|
||||
let ensInfoCache = [];
|
||||
|
||||
// Update CoinMarketCap related api calls every 5 minutes
|
||||
const timeoutCMC = CONF_TIMEOUT_CMC;
|
||||
let cmcPriceGet = 0;
|
||||
let ethPrice = 0;
|
||||
let lptPrice = 0;
|
||||
@ -54,7 +61,6 @@ let cmcQuotes = {};
|
||||
let cmcCache = {};
|
||||
|
||||
// Update Alchemy related API calls every 2 seconds
|
||||
const timeoutAlchemy = CONF_TIMEOUT_ALCHEMY;
|
||||
let l2Gwei = 0;
|
||||
let l1Gwei = 0;
|
||||
let l2block = 0;
|
||||
@ -82,8 +88,6 @@ let commissionFeeCostL2 = 0;
|
||||
let serviceUriFeeCostL1 = 0;
|
||||
let serviceUriFeeCostL2 = 0;
|
||||
|
||||
// Update O info from thegraph every 1 minute
|
||||
const timeoutTheGraph = CONF_TIMEOUT_LIVEPEER;
|
||||
// Will contain addr, lastGet, and obj of any requested O's
|
||||
let orchestratorCache = [];
|
||||
// Contains delegator addr and the address of the O they are bounded to
|
||||
@ -461,12 +465,12 @@ apiRouter.get("/grafana", async (req, res) => {
|
||||
try {
|
||||
const now = new Date().getTime();
|
||||
// Update blockchain data if the cached data has expired
|
||||
if (now - arbGet > timeoutAlchemy) {
|
||||
if (now - arbGet > CONF_TIMEOUT_ALCHEMY) {
|
||||
await parseEthBlockchain();
|
||||
arbGet = now;
|
||||
}
|
||||
// Update coin prices once their data has expired
|
||||
if (now - cmcPriceGet > timeoutCMC) {
|
||||
if (now - cmcPriceGet > CONF_TIMEOUT_CMC) {
|
||||
await parseCmc();
|
||||
cmcPriceGet = now;
|
||||
}
|
||||
@ -502,7 +506,7 @@ apiRouter.get("/cmc", async (req, res) => {
|
||||
try {
|
||||
const now = new Date().getTime();
|
||||
// Update cmc once their data has expired
|
||||
if (now - cmcPriceGet > timeoutCMC) {
|
||||
if (now - cmcPriceGet > CONF_TIMEOUT_CMC) {
|
||||
cmcPriceGet = now;
|
||||
await parseCmc();
|
||||
}
|
||||
@ -517,7 +521,7 @@ apiRouter.get("/blockchains", async (req, res) => {
|
||||
try {
|
||||
const now = new Date().getTime();
|
||||
// Update blockchain data if the cached data has expired
|
||||
if (now - arbGet > timeoutAlchemy) {
|
||||
if (now - arbGet > CONF_TIMEOUT_ALCHEMY) {
|
||||
arbGet = now;
|
||||
await parseEthBlockchain();
|
||||
}
|
||||
@ -551,7 +555,7 @@ apiRouter.get("/quotes", async (req, res) => {
|
||||
try {
|
||||
const now = new Date().getTime();
|
||||
// Update cmc once their data has expired
|
||||
if (now - cmcPriceGet > timeoutCMC) {
|
||||
if (now - cmcPriceGet > CONF_TIMEOUT_CMC) {
|
||||
cmcPriceGet = now;
|
||||
await parseCmc();
|
||||
}
|
||||
@ -596,17 +600,18 @@ const parseOrchestrator = async function (reqAddr) {
|
||||
}
|
||||
}
|
||||
if (wasCached) {
|
||||
if (now - orchestratorObj.lastGet < timeoutTheGraph) {
|
||||
if (now - orchestratorObj.lastGet < CONF_TIMEOUT_LIVEPEER) {
|
||||
needsUpdate = false;
|
||||
}
|
||||
}
|
||||
if (!wasCached || needsUpdate) {
|
||||
const orchQuery = gql`{
|
||||
transcoders(where: {id: "${reqAddr}"}) {
|
||||
transcoder(id: "${reqAddr}") {
|
||||
id
|
||||
activationRound
|
||||
deactivationRound
|
||||
active
|
||||
status
|
||||
lastRewardRound {
|
||||
id
|
||||
length
|
||||
@ -629,7 +634,7 @@ const parseOrchestrator = async function (reqAddr) {
|
||||
totalVolumeETH
|
||||
totalVolumeUSD
|
||||
serviceURI
|
||||
delegators {
|
||||
delegators(first: 1000) {
|
||||
id
|
||||
bondedAmount
|
||||
startRound
|
||||
@ -643,20 +648,22 @@ const parseOrchestrator = async function (reqAddr) {
|
||||
}
|
||||
`;
|
||||
orchestratorObj = await request("https://api.thegraph.com/subgraphs/name/livepeer/arbitrum-one", orchQuery);
|
||||
orchestratorObj = orchestratorObj.transcoders[0];
|
||||
orchestratorObj = orchestratorObj.transcoder;
|
||||
// Not found
|
||||
if (!orchestratorObj) {
|
||||
return {};
|
||||
}
|
||||
orchestratorObj.lastGet = now;
|
||||
if (wasCached) {
|
||||
for (var orch of orchestratorCache) {
|
||||
if (orch.id == reqAddr) {
|
||||
orch = orchestratorObj;
|
||||
for (var idx = 0; idx < orchestratorCache.length; idx++) {
|
||||
if (orchestratorCache[idx].id == reqAddr) {
|
||||
console.log("Updating outdated orchestrator " + orchestratorObj.id + " @ " + now);
|
||||
orchestratorCache[idx] = orchestratorObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("Pushing new orchestrator " + orchestratorObj.id + " @ " + now);
|
||||
orchestratorCache.push(orchestratorObj);
|
||||
}
|
||||
}
|
||||
@ -714,7 +721,7 @@ const parseDelegator = async function (reqAddr) {
|
||||
}
|
||||
}
|
||||
if (wasCached) {
|
||||
if (now - delegatorObj.lastGet < timeoutTheGraph) {
|
||||
if (now - delegatorObj.lastGet < CONF_TIMEOUT_LIVEPEER) {
|
||||
needsUpdate = false;
|
||||
}
|
||||
}
|
||||
@ -738,13 +745,15 @@ const parseDelegator = async function (reqAddr) {
|
||||
}
|
||||
delegatorObj.lastGet = now;
|
||||
if (wasCached) {
|
||||
for (var delegator of delegatorCache) {
|
||||
if (delegator.id == reqAddr) {
|
||||
delegator = delegatorObj;
|
||||
for (var idx = 0; idx < delegatorCache.length; idx++) {
|
||||
if (delegatorCache[idx].id == reqAddr) {
|
||||
console.log("Updating outdated delegator " + delegatorObj.id + " @ " + now);
|
||||
delegatorCache[idx] = delegatorObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("Pushing new delegator " + delegatorObj.id + " @ " + now);
|
||||
delegatorCache.push(delegatorObj);
|
||||
}
|
||||
}
|
||||
@ -804,12 +813,12 @@ apiRouter.get("/prometheus/:orchAddr", async (req, res) => {
|
||||
try {
|
||||
const now = new Date().getTime();
|
||||
// Update blockchain data if the cached data has expired
|
||||
if (now - arbGet > timeoutAlchemy) {
|
||||
if (now - arbGet > CONF_TIMEOUT_ALCHEMY) {
|
||||
await parseEthBlockchain();
|
||||
arbGet = now;
|
||||
}
|
||||
// Update coin prices once their data has expired
|
||||
if (now - cmcPriceGet > timeoutCMC) {
|
||||
if (now - cmcPriceGet > CONF_TIMEOUT_CMC) {
|
||||
await parseCmc();
|
||||
cmcPriceGet = now;
|
||||
}
|
||||
@ -950,4 +959,121 @@ apiRouter.get("/prometheus/:orchAddr", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
const getEnsDomain = async function (addr) {
|
||||
const now = new Date().getTime();
|
||||
let wasInCache = false;
|
||||
// See if it is cached
|
||||
for (const thisAddr of ensDomainCache) {
|
||||
if (thisAddr.address === addr) {
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < CONF_TIMEOUT_ENS_DOMAIN ){
|
||||
return thisAddr.domain;
|
||||
}
|
||||
wasInCache = true;
|
||||
}
|
||||
}
|
||||
// Else get it and cache it
|
||||
const ensDomain = await provider.lookupAddress(addr.toLowerCase());
|
||||
let ensObj;
|
||||
if (!ensDomain){
|
||||
ensObj = {
|
||||
domain: null,
|
||||
address: addr,
|
||||
timestamp: now
|
||||
};
|
||||
} else {
|
||||
ensObj = {
|
||||
domain: ensDomain,
|
||||
address: addr,
|
||||
timestamp: now
|
||||
};
|
||||
}
|
||||
if (wasInCache){
|
||||
for (var idx = 0; idx < ensDomainCache.length; idx++) {
|
||||
if (ensDomainCache[idx].address == addr) {
|
||||
console.log("Updating outdated domain " + ensObj.domain + " owned by " + ensObj.address + " @ " + ensObj.timestamp);
|
||||
ensDomainCache[idx] = ensObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("Caching new domain " + ensObj.domain + " owned by " + ensObj.address + " @ " + ensObj.timestamp);
|
||||
ensDomainCache.push(ensObj);
|
||||
}
|
||||
return ensObj.domain;
|
||||
}
|
||||
|
||||
const getEnsInfo = async function (addr) {
|
||||
const now = new Date().getTime();
|
||||
let wasInCache = false;
|
||||
// See if it is cached
|
||||
for (const thisAddr of ensInfoCache) {
|
||||
if (thisAddr.domain === addr) {
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < CONF_TIMEOUT_ENS_INFO ){
|
||||
return thisAddr;
|
||||
}
|
||||
wasInCache = true;
|
||||
}
|
||||
}
|
||||
// Else get it and cache it
|
||||
const resolver = await provider.getResolver(addr);
|
||||
const description = await resolver.getText("description");
|
||||
const url = await resolver.getText("url");
|
||||
const avatar = await resolver.getAvatar();
|
||||
const ensObj = {
|
||||
domain: addr,
|
||||
description,
|
||||
url,
|
||||
avatar,
|
||||
timestamp: now
|
||||
};
|
||||
if (wasInCache){
|
||||
for (var idx = 0; idx < ensInfoCache.length; idx++) {
|
||||
if (ensInfoCache[idx].domain == addr) {
|
||||
console.log("Updating outdated info " + ensObj.domain + " @ " + ensObj.timestamp);
|
||||
ensInfoCache[idx] = ensObj;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log("Caching new info " + ensObj.domain + " @ " + ensObj.timestamp);
|
||||
ensInfoCache.push(ensObj);
|
||||
}
|
||||
return ensObj;
|
||||
}
|
||||
|
||||
// Gets and caches info for a single address
|
||||
apiRouter.get("/getENS/:orch", async (req, res) => {
|
||||
try {
|
||||
// First resolve addr => domain name
|
||||
const ensDomain = await getEnsDomain(req.params.orch);
|
||||
if (!ensDomain){
|
||||
res.send({domain: null});
|
||||
return;
|
||||
}
|
||||
// Then resolve address to info
|
||||
const ensInfo = await getEnsInfo(ensDomain);
|
||||
res.send(ensInfo);
|
||||
} catch (err) {
|
||||
res.status(400).send(err);
|
||||
}
|
||||
});
|
||||
// Returns entire ENS domain mapping cache
|
||||
apiRouter.get("/getEnsDomains", async (req, res) => {
|
||||
try {
|
||||
res.send(ensDomainCache);
|
||||
} catch (err) {
|
||||
res.status(400).send(err);
|
||||
}
|
||||
});
|
||||
// Returns entire ENS info mapping cache
|
||||
apiRouter.get("/getEnsInfo", async (req, res) => {
|
||||
try {
|
||||
res.send(ensInfoCache);
|
||||
} catch (err) {
|
||||
res.status(400).send(err);
|
||||
}
|
||||
});
|
||||
|
||||
export default apiRouter;
|
BIN
public/ens.png
Normal file
BIN
public/ens.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.2 KiB |
@ -24,6 +24,8 @@ export const RECEIVE_CURRENT_ORCHESTRATOR = "RECEIVE_CURRENT_ORCHESTRATOR";
|
||||
export const RECEIVE_ORCHESTRATOR = "RECEIVE_ORCHESTRATOR";
|
||||
export const CLEAR_ORCHESTRATOR = "CLEAR_ORCHESTRATOR";
|
||||
export const RECEIVE_TICKETS = "RECEIVE_TICKETS";
|
||||
export const SET_ALL_ENS_INFO = "SET_ALL_ENS_INFO";
|
||||
export const SET_ALL_ENS_DOMAINS = "SET_ALL_ENS_DOMAINS";
|
||||
|
||||
const setQuotes = message => ({
|
||||
type: RECEIVE_QUOTES, message
|
||||
@ -46,6 +48,13 @@ const clearOrchestratorInfo = () => ({
|
||||
const setTickets = message => ({
|
||||
type: RECEIVE_TICKETS, message
|
||||
});
|
||||
const setAllEnsInfo = message => ({
|
||||
type: SET_ALL_ENS_INFO, message
|
||||
});
|
||||
const setAllEnsDomains = message => ({
|
||||
type: SET_ALL_ENS_DOMAINS, message
|
||||
});
|
||||
|
||||
|
||||
export const getQuotes = () => async dispatch => {
|
||||
const response = await apiUtil.getQuotes();
|
||||
@ -523,3 +532,27 @@ export const getOrchestratorInfo = (orchAddr) => async dispatch => {
|
||||
export const clearOrchestrator = () => async dispatch => {
|
||||
return dispatch(clearOrchestratorInfo({}));
|
||||
};
|
||||
|
||||
export const getAllEnsDomains = () => async dispatch => {
|
||||
const response = await apiUtil.getAllEnsDomains();
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
return dispatch(setAllEnsDomains(data));
|
||||
}
|
||||
return dispatch(receiveErrors(data));
|
||||
};
|
||||
|
||||
export const getAllEnsInfo = () => async dispatch => {
|
||||
const response = await apiUtil.getAllEnsInfo();
|
||||
const data = await response.json();
|
||||
if (response.ok) {
|
||||
return dispatch(setAllEnsInfo(data));
|
||||
}
|
||||
return dispatch(receiveErrors(data));
|
||||
};
|
||||
|
||||
export const getEnsInfo = async (addr) => {
|
||||
const response = await apiUtil.getEnsInfo(addr);
|
||||
const data = await response.json();
|
||||
};
|
||||
|
@ -1,14 +1,94 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { useSelector } from 'react-redux';
|
||||
import { getEnsInfo } from "../actions/livepeer";
|
||||
import {
|
||||
getOrchestratorInfo
|
||||
} from "../actions/livepeer";
|
||||
|
||||
const Address = (obj) => {
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const [hasRefreshed, setRefresh] = useState(false);
|
||||
let thisDomain = null;
|
||||
let thisInfo = null;
|
||||
const now = new Date().getTime();
|
||||
// Lookup domain in cache
|
||||
if (livepeer.ensDomainMapping){
|
||||
for (const thisAddr of livepeer.ensDomainMapping) {
|
||||
if (thisAddr.address === obj.address) {
|
||||
thisDomain = thisAddr;
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisDomain == null && !hasRefreshed) {
|
||||
setRefresh(true);
|
||||
getEnsInfo(obj.address);
|
||||
}
|
||||
}
|
||||
// Lookup current info in cache only if this addr has a mapped ENS domain
|
||||
if (thisDomain && thisDomain.domain) {
|
||||
for (const thisAddr of livepeer.ensInfoMapping) {
|
||||
if (thisAddr.domain === thisDomain.domain) {
|
||||
thisInfo = thisAddr;
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisInfo == null && !hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
let thisName;
|
||||
let thisIcon;
|
||||
if (thisInfo) {
|
||||
thisName = thisInfo.domain;
|
||||
if (thisInfo.avatar) {
|
||||
thisIcon =
|
||||
<a className="selectOrchLight" style={{cursor: 'alias'}} target="_blank" rel="noopener noreferrer" href={"https://app.ens.domains/name/" + thisInfo.domain + "/details"} >
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src={thisInfo.avatar} width="20" height="20" />
|
||||
</div>
|
||||
</a >
|
||||
} else {
|
||||
thisIcon =
|
||||
<a className="selectOrchLight" style={{cursor: 'alias'}} target="_blank" rel="noopener noreferrer" href={"https://app.ens.domains/name/" + thisInfo.domain + "/details"} >
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src="ens.png" width="20" height="20" />
|
||||
</div>
|
||||
</a >
|
||||
}
|
||||
} else {
|
||||
thisName = obj.address;
|
||||
thisIcon = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rowAlignLeft">
|
||||
<a className="selectOrchLight" target="_blank" rel="noopener noreferrer" href={"https://explorer.livepeer.org/accounts/" + obj.address} >
|
||||
<a className="selectOrchLight" style={{cursor: 'alias'}} target="_blank" rel="noopener noreferrer" href={"https://explorer.livepeer.org/accounts/" + obj.address} >
|
||||
<div className="rowAlignLeft">
|
||||
<img alt="" src="livepeer.png" width="20" height="20" />
|
||||
<span className="elipsText elipsOnMobile">{obj.address}</span>
|
||||
</div>
|
||||
</a>
|
||||
{thisIcon}
|
||||
<span className="elipsText elipsOnMobile">{thisName}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -35,9 +35,9 @@ const EventButton = (obj) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="strokeSmollLeft">
|
||||
<div className="strokeSmollLeft" style={{ width: '100%', minWidth: '200px', maxWidth: '500px'}}>
|
||||
{blockNumber}
|
||||
<div className="strokeSmollLeft" style={{ borderRadius: "1.2em", backgroundColor: obj.eventObj.eventColour, opacity: 0.9, border: '0.1em solid rgba(54, 46, 46, 0.1)', boxShadow: "4px 2px 3px 2px rgba(54, 46, 46, 0.1)" }}>
|
||||
<div className="strokeSmollLeft" style={{ width: "100%", borderRadius: "1.2em", backgroundColor: obj.eventObj.eventColour, opacity: 0.9, border: '0.1em solid rgba(54, 46, 46, 0.1)', boxShadow: "4px 2px 3px 2px rgba(54, 46, 46, 0.1)" }}>
|
||||
<div className="halfVerticalDivider" />
|
||||
<div className="rowAlignLeft">
|
||||
{eventCaller}
|
||||
|
@ -1,14 +1,85 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import {
|
||||
getOrchestratorInfo
|
||||
} from "../actions/livepeer";
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { getEnsInfo } from "../actions/livepeer";
|
||||
|
||||
const EventButtonAddress = (obj) => {
|
||||
const dispatch = useDispatch();
|
||||
const livepeer = useSelector((state) => state.livepeerstate);
|
||||
const [hasRefreshed, setRefresh] = useState(false);
|
||||
let thisDomain = null;
|
||||
let thisInfo = null;
|
||||
const now = new Date().getTime();
|
||||
// Lookup domain in cache
|
||||
if (livepeer.ensDomainMapping) {
|
||||
for (const thisAddr of livepeer.ensDomainMapping) {
|
||||
if (thisAddr.address === obj.address) {
|
||||
thisDomain = thisAddr;
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisDomain == null && !hasRefreshed) {
|
||||
setRefresh(true);
|
||||
getEnsInfo(obj.address);
|
||||
}
|
||||
}
|
||||
// Lookup current info in cache only if this addr has a mapped ENS domain
|
||||
if (thisDomain && thisDomain.domain) {
|
||||
for (const thisAddr of livepeer.ensInfoMapping) {
|
||||
if (thisAddr.domain === thisDomain.domain) {
|
||||
thisInfo = thisAddr;
|
||||
// Check timeout
|
||||
if (now - thisAddr.timestamp < 86400000) {
|
||||
break;
|
||||
}
|
||||
// Is outdated
|
||||
if (!hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If it was not cached at all
|
||||
if (thisInfo == null && !hasRefreshed) {
|
||||
getEnsInfo(obj.address);
|
||||
setRefresh(true);
|
||||
}
|
||||
}
|
||||
|
||||
let thisName;
|
||||
let thisIcon;
|
||||
if (thisInfo) {
|
||||
thisName = <h4 className="elipsText elipsOnMobileExtra">{thisInfo.domain}</h4>;
|
||||
if (thisInfo.avatar) {
|
||||
thisIcon =
|
||||
<a className="selectOrch" style={{ cursor: 'alias' }} target="_blank" rel="noopener noreferrer" href={"https://app.ens.domains/name/" + thisInfo.domain + "/details"} >
|
||||
<img alt="" src={thisInfo.avatar} width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a >
|
||||
} else {
|
||||
thisIcon =
|
||||
<a className="selectOrch" style={{ cursor: 'alias' }} target="_blank" rel="noopener noreferrer" href={"https://app.ens.domains/name/" + thisInfo.domain + "/details"} >
|
||||
<img alt="" src="ens.png" width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a >
|
||||
}
|
||||
} else {
|
||||
thisName = <span className="elipsText elipsOnMobileExtra">{obj.address}</span>;
|
||||
thisIcon = null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rowAlignLeft" style={{ width: '100%' }}>
|
||||
{thisIcon}
|
||||
<a className="selectOrch" style={{ cursor: 'alias' }} rel="noopener noreferrer" target="_blank" href={"https://explorer.livepeer.org/accounts/" + obj.address}>
|
||||
<img alt="" src="livepeer.png" width="20em" height="20em" style={{ margin: 0 }} />
|
||||
</a>
|
||||
@ -17,7 +88,7 @@ const EventButtonAddress = (obj) => {
|
||||
</button>
|
||||
<span>{obj.name}</span>
|
||||
<button className="selectOrch" style={{ padding: '0.5em', cursor: 'help' }} onClick={() => { dispatch(getOrchestratorInfo(obj.address)) }} >
|
||||
<span className="elipsText elipsOnMobileExtra">{obj.address}</span>
|
||||
{thisName}
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useState, useEffect } from 'react'
|
||||
import '../style.css';
|
||||
import { Navigate, useSearchParams } from "react-router-dom";
|
||||
import { useSelector, useDispatch } from 'react-redux'
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
import { getOrchestratorInfo, clearOrchestrator } from "../actions/livepeer";
|
||||
import EventViewer from "../components/eventViewer";
|
||||
import Orchestrator from "../components/orchestratorViewer";
|
||||
|
@ -4,7 +4,8 @@ import {
|
||||
getVisitorStats
|
||||
} from "../actions/user";
|
||||
import {
|
||||
getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo, getTickets
|
||||
getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo, getTickets,
|
||||
getAllEnsDomains, getAllEnsInfo
|
||||
} from "../actions/livepeer";
|
||||
import { login } from "../actions/session";
|
||||
|
||||
@ -18,7 +19,7 @@ const Startup = (obj) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const refreshAllZeData = () => {
|
||||
console.log("Refreshing data...");
|
||||
console.log("Refreshing Livepeer data...");
|
||||
batch(() => {
|
||||
dispatch(getQuotes());
|
||||
dispatch(getEvents());
|
||||
@ -36,9 +37,18 @@ const Startup = (obj) => {
|
||||
});
|
||||
}
|
||||
|
||||
const refreshENS = () => {
|
||||
console.log("Refreshing ENS data...");
|
||||
batch(() => {
|
||||
dispatch(getAllEnsDomains());
|
||||
dispatch(getAllEnsInfo());
|
||||
});
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
refreshLogin();
|
||||
refreshAllZeData();
|
||||
refreshENS();
|
||||
setIsLoaded(true);
|
||||
if (refreshInterval) {
|
||||
const interval = setInterval(refreshAllZeData, refreshInterval);
|
||||
|
@ -5,10 +5,21 @@ import {
|
||||
RECEIVE_ORCHESTRATOR,
|
||||
RECEIVE_CURRENT_ORCHESTRATOR,
|
||||
CLEAR_ORCHESTRATOR,
|
||||
RECEIVE_TICKETS
|
||||
RECEIVE_TICKETS,
|
||||
SET_ALL_ENS_INFO,
|
||||
SET_ALL_ENS_DOMAINS
|
||||
} from "../../actions/livepeer";
|
||||
|
||||
export default (state = {}, { type, message }) => {
|
||||
export default (state = {
|
||||
quotes: [],
|
||||
blockchains: [],
|
||||
events: [],
|
||||
thisOrchestrator: null,
|
||||
selectedOrchestrator: null,
|
||||
tickets: [],
|
||||
ensInfoMapping: [],
|
||||
ensDomainMapping: []
|
||||
}, { type, message }) => {
|
||||
Object.freeze(state);
|
||||
switch (type) {
|
||||
case RECEIVE_QUOTES:
|
||||
@ -25,6 +36,10 @@ export default (state = {}, { type, message }) => {
|
||||
return { ...state, selectedOrchestrator: null };
|
||||
case RECEIVE_TICKETS:
|
||||
return { ...state, tickets: message };
|
||||
case SET_ALL_ENS_INFO:
|
||||
return { ...state, ensInfoMapping: message };
|
||||
case SET_ALL_ENS_DOMAINS:
|
||||
return { ...state, ensDomainMapping: message };
|
||||
default:
|
||||
return { ...state };
|
||||
}
|
||||
|
@ -62,3 +62,30 @@ export const getOrchestratorByDelegator = (delAddr) => (
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
export const getAllEnsDomains = () => (
|
||||
fetch("api/livepeer/getEnsDomains/", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
export const getAllEnsInfo = () => (
|
||||
fetch("api/livepeer/getEnsInfo/", {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
export const getEnsInfo = (addr) => (
|
||||
fetch("api/livepeer/getENS/" + addr, {
|
||||
method: "GET",
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
})
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user