From 8c5721560a385eea3d92240fcdb8f303df1c0dbb Mon Sep 17 00:00:00 2001 From: Marco van Dijk Date: Tue, 22 Mar 2022 01:36:59 +0100 Subject: [PATCH] Quick n dirty 3box support --- backend/src/routes/livepeer.js | 75 +++++++++++++++++++++++++- src/actions/livepeer.js | 19 +++++++ src/components/OrchAddressViewer.js | 31 ++++++++++- src/components/OrchInfoViewer.js | 40 +++++++++++++- src/components/eventButtonAddress.js | 68 ++++++++++++++++++----- src/pages/loadingScreen.js | 3 +- src/reducers/livepeer/livepeerstate.js | 5 +- src/util/livepeer.js | 18 +++++++ 8 files changed, 240 insertions(+), 19 deletions(-) diff --git a/backend/src/routes/livepeer.js b/backend/src/routes/livepeer.js index 14d6893..e016036 100644 --- a/backend/src/routes/livepeer.js +++ b/backend/src/routes/livepeer.js @@ -52,6 +52,7 @@ const provider = new ethers.providers.JsonRpcProvider(API_L1_HTTP); // const ens = new ENS({ provider: web3layer1, ensAddress: getEnsAddress('1') }); let ensDomainCache = []; let ensInfoCache = []; +let threeboxCache = []; // Update CoinMarketCap related api calls every 5 minutes let cmcPriceGet = 0; @@ -677,7 +678,7 @@ const parseOrchestrator = async function (reqAddr) { return orchestratorCache[idx]; } } - } else{ + } else { console.log("Thegraph is probably acting up, but there is no cached value. Returning null..."); return {}; } @@ -1056,7 +1057,6 @@ const getEnsInfo = async function (addr) { } return ensObj; } - // Gets and caches info for a single address apiRouter.get("/getENS/:orch", async (req, res) => { try { @@ -1090,4 +1090,75 @@ apiRouter.get("/getEnsInfo", async (req, res) => { } }); + +const getThreeBoxInfo = async function (addr) { + const now = new Date().getTime(); + let wasInCache = false; + // See if it is cached + for (const thisAddr of threeboxCache) { + if (thisAddr.address === addr) { + // Check timeout + if (now - thisAddr.timestamp < CONF_TIMEOUT_ENS_INFO) { + return thisAddr; + } + wasInCache = true; + } + } + // Else get it and cache it + const url = "https://explorer.livepeer.org/api/3box?account=" + addr; + await https.get(url, (res) => { + let body = ""; + res.on("data", (chunk) => { + body += chunk; + }); + res.on("end", () => { + try { + const data = JSON.parse(body); + const threeBoxObj = { + address: data.id, + name: data.name, + website: data.website, + description: data.description, + image: data.image, + timestamp: now + } + if (wasInCache) { + for (var idx = 0; idx < threeboxCache.length; idx++) { + if (threeboxCache[idx].address == addr) { + console.log("Updating outdated 3box info " + threeBoxObj.address + " @ " + threeBoxObj.timestamp); + threeboxCache[idx] = threeBoxObj; + break; + } + } + } else { + console.log("Caching new 3box info " + threeBoxObj.address + " @ " + threeBoxObj.timestamp); + threeboxCache.push(threeBoxObj); + } + } catch (error) { + console.error(error.message); + }; + }); + }).on("error", (error) => { + console.error(error.message); + }); +} +// Gets and caches info for a single address +apiRouter.get("/getThreeBox/:orch", async (req, res) => { + try { + // First resolve addr => domain name + const threeBoxInfo = await getThreeBoxInfo(req.params.orch); + res.send(threeBoxInfo); + } catch (err) { + res.status(400).send(err); + } +}); +// Returns entire 3box info mapping cache +apiRouter.get("/getAllThreeBox", async (req, res) => { + try { + res.send(threeboxCache); + } catch (err) { + res.status(400).send(err); + } +}); + export default apiRouter; \ No newline at end of file diff --git a/src/actions/livepeer.js b/src/actions/livepeer.js index 34cf27c..350617a 100644 --- a/src/actions/livepeer.js +++ b/src/actions/livepeer.js @@ -26,6 +26,7 @@ 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"; +export const SET_ALL_THREEBOX_INFO = "SET_ALL_THREEBOX_INFO"; const setQuotes = message => ({ type: RECEIVE_QUOTES, message @@ -54,6 +55,9 @@ const setAllEnsInfo = message => ({ const setAllEnsDomains = message => ({ type: SET_ALL_ENS_DOMAINS, message }); +const setAllThreeBoxInfo = message => ({ + type: SET_ALL_THREEBOX_INFO, message +}); export const getQuotes = () => async dispatch => { @@ -552,4 +556,19 @@ export const getEnsInfo = async (addr) => { const response = await apiUtil.getEnsInfo(addr); const data = await response.json(); }; + + +export const getAllThreeBoxInfo = () => async dispatch => { + const response = await apiUtil.getAllThreeBox(); + const data = await response.json(); + if (response.ok) { + return dispatch(setAllThreeBoxInfo(data)); + } + return dispatch(receiveErrors(data)); +}; + +export const getThreeBoxInfo = async (addr) => { + const response = await apiUtil.getThreeBox(addr); + const data = await response.json(); +}; \ No newline at end of file diff --git a/src/components/OrchAddressViewer.js b/src/components/OrchAddressViewer.js index bac23c5..b8762f4 100644 --- a/src/components/OrchAddressViewer.js +++ b/src/components/OrchAddressViewer.js @@ -5,6 +5,8 @@ import { getEnsInfo } from "../actions/livepeer"; const Address = (obj) => { const livepeer = useSelector((state) => state.livepeerstate); const [hasRefreshed, setRefresh] = useState(false); + let hasENS = false; + let hasThreeBox = false; let thisDomain = null; let thisInfo = null; const now = new Date().getTime(); @@ -36,6 +38,7 @@ const Address = (obj) => { for (const thisAddr of livepeer.ensInfoMapping) { if (thisAddr.domain === thisDomain.domain) { thisInfo = thisAddr; + hasENS = true; // Check timeout if (now - thisAddr.timestamp < 86400000) { break; @@ -55,9 +58,22 @@ const Address = (obj) => { } } + // Ugly shit, but temporary for now to quickly enable threebox. Sorry! + if (!hasENS) { + if (livepeer.threeBoxInfo) { + for (const thisAddr of livepeer.threeBoxInfo) { + if (thisAddr.address === obj.address) { + thisInfo = thisAddr; + hasThreeBox = true; + break; + } + } + } + } + let thisName; let thisIcon; - if (thisInfo) { + if (hasENS) { thisName = thisInfo.domain; console.log(thisInfo.avatar); if (thisInfo.avatar) { @@ -71,13 +87,24 @@ const Address = (obj) => { } + } else if (hasThreeBox) { + if (thisInfo.name) { + thisName =

{thisInfo.name}

; + } else { + thisName = {obj.address}; + } + if (thisInfo.image) { + thisIcon = + } else { + thisIcon = null; + } } else { thisName = obj.address; thisIcon = null; } return ( -
+
diff --git a/src/components/OrchInfoViewer.js b/src/components/OrchInfoViewer.js index 437bce3..53285c2 100644 --- a/src/components/OrchInfoViewer.js +++ b/src/components/OrchInfoViewer.js @@ -26,6 +26,8 @@ function copyLink(addr) { const OrchInfoViewer = (obj) => { const livepeer = useSelector((state) => state.livepeerstate); + let hasENS = false; + let hasThreeBox = false; let rewardCut = 0; let feeCut = 0; let totalStake = 0; @@ -86,13 +88,28 @@ const OrchInfoViewer = (obj) => { for (const thisAddr of livepeer.ensInfoMapping) { if (thisAddr.domain === thisDomain.domain) { thisInfo = thisAddr; + hasENS = true; break; } } } + + // Ugly shit, but temporary for now to quickly enable threebox. Sorry! + if (!hasENS) { + if (livepeer.threeBoxInfo) { + for (const thisAddr of livepeer.threeBoxInfo) { + if (thisAddr.address === thisID) { + thisInfo = thisAddr; + hasThreeBox = true; + break; + } + } + } + } + let ensDescription; let ensUrl; - if (thisInfo) { + if (hasENS) { if (thisInfo.description) { ensDescription =
@@ -113,6 +130,27 @@ const OrchInfoViewer = (obj) => {
} + } else if (hasThreeBox) { + if (thisInfo.description) { + ensDescription = +
+
+ {thisInfo.description} +
+ } + if (thisInfo.website) { + if (!thisInfo.website.startsWith('http')) { + thisInfo.website = "https://" + thisInfo.website; + } + ensUrl = +
+ +
+ {thisInfo.website} +
+
+
+ } } return ( diff --git a/src/components/eventButtonAddress.js b/src/components/eventButtonAddress.js index 78b0c91..6407512 100644 --- a/src/components/eventButtonAddress.js +++ b/src/components/eventButtonAddress.js @@ -1,16 +1,18 @@ import React, { useState } from "react"; import { - getOrchestratorInfo + getOrchestratorInfo, getEnsInfo, getThreeBoxInfo } from "../actions/livepeer"; 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); + const [hasThreeBoxRefreshed, setThreeBoxRefresh] = useState(false); let thisDomain = null; let thisInfo = null; + let hasENS = false; + let hasThreeBox = false; const now = new Date().getTime(); // Lookup domain in cache if (livepeer.ensDomainMapping) { @@ -40,6 +42,7 @@ const EventButtonAddress = (obj) => { for (const thisAddr of livepeer.ensInfoMapping) { if (thisAddr.domain === thisDomain.domain) { thisInfo = thisAddr; + hasENS = true; // Check timeout if (now - thisAddr.timestamp < 86400000) { break; @@ -59,21 +62,62 @@ const EventButtonAddress = (obj) => { } } + // Ugly shit, but temporary for now to quickly enable threebox. Sorry! + if (!hasENS) { + if (livepeer.threeBoxInfo) { + for (const thisAddr of livepeer.threeBoxInfo) { + if (thisAddr.address === obj.address) { + thisInfo = thisAddr; + hasThreeBox = true; + // Check timeout + if (now - thisAddr.timestamp < 86400000) { + break; + } + // Is outdated + if (!hasThreeBoxRefreshed) { + getThreeBoxInfo(obj.address); + setThreeBoxRefresh(true); + } + break; + } + } + // If it was not cached at all + if (thisDomain == null && !hasThreeBoxRefreshed) { + setThreeBoxRefresh(true); + getThreeBoxInfo(obj.address); + } + } + } + let thisName; let thisIcon; - if (thisInfo) { - thisName =

{thisInfo.domain}

; - if (thisInfo.avatar) { - thisIcon = - - - + if (hasENS) { + if (thisInfo) { + thisName =

{thisInfo.domain}

; + if (thisInfo.avatar) { + thisIcon = + + + + } + } else { + thisName = {obj.address}; + thisIcon = null; + } + } else if (hasThreeBox) { + if (thisInfo.name) { + thisName =

{thisInfo.name}

; + } else { + thisName = {obj.address}; + } + if (thisInfo.image) { + thisIcon = + } else { + thisIcon = null; } - } else { - thisName = {obj.address}; - thisIcon = null; } + return (
diff --git a/src/pages/loadingScreen.js b/src/pages/loadingScreen.js index 8131bb9..4402f67 100644 --- a/src/pages/loadingScreen.js +++ b/src/pages/loadingScreen.js @@ -5,7 +5,7 @@ import { } from "../actions/user"; import { getQuotes, getBlockchainData, getEvents, getCurrentOrchestratorInfo, getTickets, - getAllEnsDomains, getAllEnsInfo + getAllEnsDomains, getAllEnsInfo, getAllThreeBoxInfo } from "../actions/livepeer"; import { login } from "../actions/session"; @@ -40,6 +40,7 @@ const Startup = (obj) => { const refreshENS = () => { console.log("Refreshing ENS data..."); batch(() => { + dispatch(getAllThreeBoxInfo()); dispatch(getAllEnsDomains()); dispatch(getAllEnsInfo()); }); diff --git a/src/reducers/livepeer/livepeerstate.js b/src/reducers/livepeer/livepeerstate.js index 15da7c1..c7a2f3a 100644 --- a/src/reducers/livepeer/livepeerstate.js +++ b/src/reducers/livepeer/livepeerstate.js @@ -7,7 +7,8 @@ import { CLEAR_ORCHESTRATOR, RECEIVE_TICKETS, SET_ALL_ENS_INFO, - SET_ALL_ENS_DOMAINS + SET_ALL_ENS_DOMAINS, + SET_ALL_THREEBOX_INFO } from "../../actions/livepeer"; export default (state = { @@ -40,6 +41,8 @@ export default (state = { return { ...state, ensInfoMapping: message }; case SET_ALL_ENS_DOMAINS: return { ...state, ensDomainMapping: message }; + case SET_ALL_THREEBOX_INFO: + return { ...state, threeBoxInfo: message }; default: return { ...state }; } diff --git a/src/util/livepeer.js b/src/util/livepeer.js index 5179024..5c0a176 100644 --- a/src/util/livepeer.js +++ b/src/util/livepeer.js @@ -89,3 +89,21 @@ export const getEnsInfo = (addr) => ( } }) ); + +export const getAllThreeBox = () => ( + fetch("api/livepeer/getAllThreeBox/", { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +); + +export const getThreeBox = (addr) => ( + fetch("api/livepeer/getThreeBox/" + addr, { + method: "GET", + headers: { + "Content-Type": "application/json" + } + }) +);