From 49f112519045dc93e6512582bb9a8aa7ac73f731 Mon Sep 17 00:00:00 2001 From: Torresmorah Date: Thu, 7 Sep 2023 16:43:40 -0600 Subject: [PATCH 01/10] feat(webapp): add filter to evm endpoints health check --- webapp/src/language/en.json | 3 +- webapp/src/language/es.json | 3 +- webapp/src/routes/EVMEndpointsList/index.js | 60 ++++++++++++------- webapp/src/routes/EVMEndpointsList/styles.js | 27 ++++++++- .../EVMEndpointsList/useRPCEndpointsState.js | 7 ++- 5 files changed, 73 insertions(+), 27 deletions(-) diff --git a/webapp/src/language/en.json b/webapp/src/language/en.json index 1ae0c286..5dc41b2b 100644 --- a/webapp/src/language/en.json +++ b/webapp/src/language/en.json @@ -457,6 +457,7 @@ "rpcEndpoint": "RPC Endpoint", "latency": "Latency", "lastBlock": "Last block", - "rerun": "Re-run health checks" + "rerun": "Re-run health checks", + "filterEndpoints": "Filter responding endpoints" } } diff --git a/webapp/src/language/es.json b/webapp/src/language/es.json index 44e742f7..41d2c6ea 100644 --- a/webapp/src/language/es.json +++ b/webapp/src/language/es.json @@ -476,6 +476,7 @@ "rpcEndpoint": "Punto final RPC", "latency": "Latencia", "lastBlock": "Último bloque", - "rerun": "Reejecutar las pruebas" + "rerun": "Reejecutar las pruebas", + "filterEndpoints": "Filtrar puntos finales" } } diff --git a/webapp/src/routes/EVMEndpointsList/index.js b/webapp/src/routes/EVMEndpointsList/index.js index 51b02158..8e725e18 100644 --- a/webapp/src/routes/EVMEndpointsList/index.js +++ b/webapp/src/routes/EVMEndpointsList/index.js @@ -11,6 +11,7 @@ import TableContainer from '@mui/material/TableContainer' import TableHead from '@mui/material/TableHead' import TableRow from '@mui/material/TableRow' import Typography from '@mui/material/Typography' +import Switch from '@mui/material/Switch' import AutorenewOutlinedIcon from '@mui/icons-material/AutorenewOutlined' import HealthCheck from 'components/HealthCheck' @@ -20,14 +21,15 @@ import HealthInfoModal from '../../components/HealthCheck/InfoModal' import styles from './styles' import useRPCEndpointsState from './useRPCEndpointsState' import { getStatus, formatWithThousandSeparator } from 'utils' +import { generalConfig } from 'config' const useStyles = makeStyles(styles) const EVMEndpointsList = () => { const classes = useStyles() const { t } = useTranslation('evmEndpointsRoute') - - const [{ endpoints }, { runHealthCheck }] = useRPCEndpointsState() + const [{ endpoints, filter }, { runHealthCheck, handleFilter }] = useRPCEndpointsState() + const { healthLights } = generalConfig return ( @@ -38,7 +40,8 @@ const EVMEndpointsList = () => { -
+
+
+
+
+ + {t('filterEndpoints')} + + { + handleFilter(event.target?.checked) + }} + /> +
@@ -61,24 +77,26 @@ const EVMEndpointsList = () => { {endpoints?.map((endpoint, index) => ( - - -
- {endpoint.url} - - - -
-
- - {formatWithThousandSeparator(endpoint.height) || 'N/A'} - - - {endpoint.latency - ? `${formatWithThousandSeparator(endpoint.latency)} ms` - : 'N/A'} - -
+ (!filter || getStatus(endpoint) !== healthLights.redLight) && ( + + +
+ {endpoint.url} + + + +
+
+ + {formatWithThousandSeparator(endpoint.height) || 'N/A'} + + + {endpoint.latency + ? `${formatWithThousandSeparator(endpoint.latency)} ms` + : 'N/A'} + +
+ ) ))}
diff --git a/webapp/src/routes/EVMEndpointsList/styles.js b/webapp/src/routes/EVMEndpointsList/styles.js index aa5b25f6..2dcb0ae2 100644 --- a/webapp/src/routes/EVMEndpointsList/styles.js +++ b/webapp/src/routes/EVMEndpointsList/styles.js @@ -4,7 +4,7 @@ export default (theme) => ({ }, healthContainer: { display: 'flex', - maxWidth: '300px', + width: '300px', justifyContent: 'space-between', }, titleContainer: { @@ -12,17 +12,38 @@ export default (theme) => ({ gap: theme.spacing(4), alignItems: 'center', }, - buttonContainer: { - padding: '0 0 0 25%', + formContainer: { + padding: '0 25% 0', marginTop: theme.spacing(4), + display: 'flex', + justifyContent: 'space-between', + flexWrap: 'wrap', + [theme.breakpoints.down('lg')]: { + padding: '0 12% 0', + }, [theme.breakpoints.down('md')]: { padding: 0, }, }, + buttonContainer: { + marginTop: theme.spacing(4), + [theme.breakpoints.down('sm')]: { + paddingRight: theme.spacing(4), + }, + }, + switchContainer: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + [theme.breakpoints.down('sm')]: { + paddingTop: theme.spacing(4), + }, + }, tableContainer: { display: 'flex', flexDirection: 'column', alignItems: 'center', + minHeight: '80vh', '& .MuiTableContainer-root': { width: '80%', [theme.breakpoints.down('md')]: { diff --git a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js index 2df17ed7..0ebc449d 100644 --- a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js +++ b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js @@ -5,6 +5,11 @@ import { evmConfig } from '../../config' const useRPCEndpointsState = () => { const [endpoints, setEndpoints] = useState(evmConfig.endpoints.map(url => ({ url, response: {} }))) + const [filter, setFilter] = useState(true) + + const handleFilter = () => { + setFilter(prev => !prev) + } const customAxios = axios.create() @@ -102,7 +107,7 @@ const useRPCEndpointsState = () => { // eslint-disable-next-line }, []) - return [{ endpoints }, { runHealthCheck }] + return [{ endpoints, filter }, { runHealthCheck, handleFilter }] } export default useRPCEndpointsState From 9c4bb51dea496bc6dbd5977a2ad4d76541971fc6 Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Fri, 8 Sep 2023 00:31:13 -0600 Subject: [PATCH 02/10] feat(proton): add cpu benchmarks for proton mainnet sitemap --- webapp/public/sitemap.proton.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/webapp/public/sitemap.proton.xml b/webapp/public/sitemap.proton.xml index bac35e1c..d90a0607 100644 --- a/webapp/public/sitemap.proton.xml +++ b/webapp/public/sitemap.proton.xml @@ -32,6 +32,10 @@ https://proton.antelope.tools/nodes-distribution 2023-09-07 + + https://proton.antelope.tools/cpu-benchmark + 2023-09-07 + https://proton.antelope.tools/ricardian-contract 2023-09-07 From 30c20cba2d54092708d50e0d798b8905f005c5f3 Mon Sep 17 00:00:00 2001 From: Torresmorah Date: Fri, 8 Sep 2023 13:45:02 -0600 Subject: [PATCH 03/10] refactor(webapp): format code --- webapp/src/routes/EVMEndpointsList/index.js | 27 ++++++++++--------- webapp/src/routes/EVMEndpointsList/styles.js | 2 +- .../EVMEndpointsList/useRPCEndpointsState.js | 7 +++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/webapp/src/routes/EVMEndpointsList/index.js b/webapp/src/routes/EVMEndpointsList/index.js index 8e725e18..6f03ba26 100644 --- a/webapp/src/routes/EVMEndpointsList/index.js +++ b/webapp/src/routes/EVMEndpointsList/index.js @@ -14,8 +14,8 @@ import Typography from '@mui/material/Typography' import Switch from '@mui/material/Switch' import AutorenewOutlinedIcon from '@mui/icons-material/AutorenewOutlined' -import HealthCheck from 'components/HealthCheck' -import HealthCheckInfo from 'components/HealthCheck/HealthCheckInfo' +import HealthCheck from '../../components/HealthCheck' +import HealthCheckInfo from '../../components/HealthCheck/HealthCheckInfo' import HealthInfoModal from '../../components/HealthCheck/InfoModal' import styles from './styles' @@ -28,7 +28,8 @@ const useStyles = makeStyles(styles) const EVMEndpointsList = () => { const classes = useStyles() const { t } = useTranslation('evmEndpointsRoute') - const [{ endpoints, filter }, { runHealthCheck, handleFilter }] = useRPCEndpointsState() + const [{ endpoints, filter }, { runHealthCheck, handleFilter }] = + useRPCEndpointsState() const { healthLights } = generalConfig return ( @@ -42,15 +43,15 @@ const EVMEndpointsList = () => {
- +
@@ -58,7 +59,7 @@ const EVMEndpointsList = () => { { handleFilter(event.target?.checked) }} diff --git a/webapp/src/routes/EVMEndpointsList/styles.js b/webapp/src/routes/EVMEndpointsList/styles.js index 2dcb0ae2..b8a291f0 100644 --- a/webapp/src/routes/EVMEndpointsList/styles.js +++ b/webapp/src/routes/EVMEndpointsList/styles.js @@ -51,7 +51,7 @@ export default (theme) => ({ }, [theme.breakpoints.up('lg')]: { width: '50%', - } + }, }, }, }) diff --git a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js index 0ebc449d..7d00a94f 100644 --- a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js +++ b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js @@ -104,10 +104,13 @@ const useRPCEndpointsState = () => { useEffect(() => { runHealthCheck() - // eslint-disable-next-line + // eslint-disable-next-line }, []) - return [{ endpoints, filter }, { runHealthCheck, handleFilter }] + return [ + { endpoints, filter }, + { runHealthCheck, handleFilter }, + ] } export default useRPCEndpointsState From 86370bcd9ccc13407d1b9c7ec20ce1b3ef725c72 Mon Sep 17 00:00:00 2001 From: Torresmorah Date: Fri, 8 Sep 2023 16:44:06 -0600 Subject: [PATCH 04/10] fix(webapp): avoid to query data obtained by subscription --- webapp/src/components/EndpointsTable/index.js | 106 ++++++++---------- .../src/components/EndpointsTextList/index.js | 58 ---------- .../components/EndpointsTextList/styles.js | 16 --- webapp/src/gql/producer.gql.js | 31 +++++ .../customHooks/useBlockProducerState.js | 21 +++- .../hooks/customHooks/useEndpointsState.js | 38 +++++-- webapp/src/hooks/customHooks/useNodeState.js | 29 +++-- .../src/hooks/customHooks/useSearchState.js | 31 ++--- webapp/src/language/en.json | 2 - webapp/src/language/es.json | 2 - webapp/src/routes/EndpointsList/index.js | 2 +- 11 files changed, 153 insertions(+), 183 deletions(-) delete mode 100644 webapp/src/components/EndpointsTextList/index.js delete mode 100644 webapp/src/components/EndpointsTextList/styles.js diff --git a/webapp/src/components/EndpointsTable/index.js b/webapp/src/components/EndpointsTable/index.js index 1fa71123..919cae1d 100644 --- a/webapp/src/components/EndpointsTable/index.js +++ b/webapp/src/components/EndpointsTable/index.js @@ -1,8 +1,8 @@ -import React, { useState } from 'react' +import React, { useState, useEffect } from 'react' +import { useLazyQuery } from '@apollo/client' import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' import { makeStyles } from '@mui/styles' -import Button from '@mui/material/Button' import Table from '@mui/material/Table' import TableBody from '@mui/material/TableBody' import TableCell from '@mui/material/TableCell' @@ -11,35 +11,62 @@ import TableHead from '@mui/material/TableHead' import TableRow from '@mui/material/TableRow' import Typography from '@mui/material/Typography' import { Tooltip as MUITooltip } from '@mui/material' -import ListAltIcon from '@mui/icons-material/ListAlt' import { Link as RouterLink } from 'react-router-dom' import Link from '@mui/material/Link' import QueryStatsIcon from '@mui/icons-material/QueryStats' +import CopyToClipboard from '../CopyToClipboard' import HealthCheck from '../HealthCheck' -import HealthCheckInfo from 'components/HealthCheck/HealthCheckInfo' +import HealthCheckInfo from '../HealthCheck/HealthCheckInfo' import { getStatus } from 'utils' +import { ENDPOINTS_QUERY } from '../../gql' import styles from './styles' -import Tooltip from '../Tooltip' -import EndpointsTextList from '../EndpointsTextList' const useStyles = makeStyles(styles) const EndpointsTable = ({ producers }) => { const classes = useStyles() const { t } = useTranslation('endpointsListRoute') - const [anchorEl, setAnchorEl] = useState(null) - const [type, setType] = useState('') + const [textLists, setTextLists] = useState({}) + const [loadProducers, { data: { producers: bpsWorkingEndpoints } = {} }] = + useLazyQuery(ENDPOINTS_QUERY) - const handlePopoverOpen = (target, type) => { - setAnchorEl(target) - setType(type) - } + useEffect(()=>{ + loadProducers({ + variables: { + where: { + response: { _contains: { isWorking: true } }, + }, + }, + }) + },[loadProducers]) - const handlePopoverClose = () => { - setAnchorEl(null) - } + useEffect(() => { + if (!bpsWorkingEndpoints?.length) return + + let endpointsList = {api:'',p2p:'',ssl:''} + + Object.keys(endpointsList).forEach(type => { + endpointsList[type] += `# List of available ${type.toUpperCase()} endpoints \n` + + bpsWorkingEndpoints.forEach(producer => { + if (!!producer?.endpoints?.length && producer.endpoints.some(endpoint=>endpoint.type===type)) { + endpointsList[type] += `# ${producer.owner} \n` + producer.endpoints.forEach(endpoint => { + if (endpoint.type === type) { + endpointsList[type] += `${type === 'p2p' ? 'p2p-peer-address = ' : ''} ${ + endpoint.value + } \n` + } + }) + endpointsList[type] += '\n' + } + }) + }) + + setTextLists(endpointsList) + }, [bpsWorkingEndpoints]) const CellList = ({ producer, endpointType }) => { return ( @@ -65,17 +92,6 @@ const EndpointsTable = ({ producers }) => { return ( <> - - - @@ -84,49 +100,19 @@ const EndpointsTable = ({ producers }) => {
{t('api')} - -
+ +
{t('ssl')} - +
{t('p2p')} - +
diff --git a/webapp/src/components/EndpointsTextList/index.js b/webapp/src/components/EndpointsTextList/index.js deleted file mode 100644 index 51429991..00000000 --- a/webapp/src/components/EndpointsTextList/index.js +++ /dev/null @@ -1,58 +0,0 @@ -import React, { useEffect, useState } from 'react' -import { useTranslation } from 'react-i18next' -import { makeStyles } from '@mui/styles' - -import useEndpointsState from '../../hooks/customHooks/useEndpointsState' -import CopyToClipboard from '../CopyToClipboard' - -import styles from './styles' - -const useStyles = makeStyles(styles) - -const EndpointsTextList = ({ type }) => { - const classes = useStyles() - const { t } = useTranslation('endpointsListRoute') - const [textList, setTextList] = useState('') - const [{ loading, producers }, { handleFilter, setPagination }] = - useEndpointsState({ useCache: true }) - - // Gets all responding endpoints - useEffect(() => { - setPagination(prev => ({ ...prev, limit: null })) - handleFilter(true) - }, [type, handleFilter, setPagination]) - - useEffect(() => { - if (!producers?.length) return - - let endpointsList = `# List of available ${type.toUpperCase()} endpoints \n` - - producers.forEach(producer => { - if (!!producer?.endpoints[type]?.length) { - endpointsList += `# ${producer.name} \n` - producer.endpoints[type].forEach(endpoint => { - endpointsList += `${type === 'p2p' ? 'p2p-peer-address = ' : ''} ${ - endpoint.value - } \n` - }) - endpointsList += '\n' - } - }) - - setTextList(endpointsList) - }, [producers, type]) - - return ( - <> - {!loading && !!textList?.length && ( -
-

{t('listOfResponding')}

- - {textList} -
- )} - - ) -} - -export default EndpointsTextList diff --git a/webapp/src/components/EndpointsTextList/styles.js b/webapp/src/components/EndpointsTextList/styles.js deleted file mode 100644 index 85699ad6..00000000 --- a/webapp/src/components/EndpointsTextList/styles.js +++ /dev/null @@ -1,16 +0,0 @@ -export default (theme) => ({ - container: { - display: 'flex', - flexDirection: 'column', - padding: theme.spacing(0, 2, 2), - whiteSpace: 'pre-line', - minWidth: '300px', - '& p': { - margin: theme.spacing(0, 0, 2, 0), - fontWeight: 'bold', - [theme.breakpoints.up('md')]: { - textAlign: 'center', - }, - }, - }, -}) diff --git a/webapp/src/gql/producer.gql.js b/webapp/src/gql/producer.gql.js index 888e3d34..786fc0d7 100644 --- a/webapp/src/gql/producer.gql.js +++ b/webapp/src/gql/producer.gql.js @@ -38,6 +38,19 @@ export const PRODUCERS_QUERY = gql` } } ` + +export const PRODUCERS_COUNT_QUERY = gql` + query producer( + $where: producer_bool_exp + ) { + info: producer_aggregate(where: $where) { + producers: aggregate { + count + } + } + } +` + export const NODES_SUBSCRIPTION = gql` subscription ($offset: Int = 0, $limit: Int = 21, $where: producer_bool_exp) { producers: producer( @@ -96,6 +109,24 @@ export const ENDPOINTS_SUBSCRIPTION = gql` } ` +export const ENDPOINTS_QUERY = gql` + query producer( + $where: endpoints_by_producer_id_bool_exp! + ) { + producers: producer( + where: {endpoints_list: {_and: [{type: {_gt: ""}}, $where]}} + order_by: { total_votes_percent: desc } + ) { + id + owner + endpoints: endpoints_list(where: $where) { + type + value + } + } + } +` + export const NODE_CPU_BENCHMARK = gql` query ($account: String) { cpu( diff --git a/webapp/src/hooks/customHooks/useBlockProducerState.js b/webapp/src/hooks/customHooks/useBlockProducerState.js index 271c785b..d00c83a8 100644 --- a/webapp/src/hooks/customHooks/useBlockProducerState.js +++ b/webapp/src/hooks/customHooks/useBlockProducerState.js @@ -26,16 +26,27 @@ const CHIPS_FILTERS = [ const CHIPS_NAMES = ['all', ...eosConfig.producerTypes] const useBlockProducerState = () => { - const [ - { filters, pagination, producers }, - { handleOnSearch, handleOnPageChange, setPagination }, - ] = useSearchState({ query: PRODUCERS_QUERY }) + const defaultVariables = { + limit: 20, + offset: 0, + endpointFilter: undefined, + where: { + owner: { _like: '%%' }, + nodes: { endpoints: { value: { _gt: '' } } }, + } + } + const [variables, setVariables] = useState(defaultVariables) + const [loadProducers, { data: { info, producers } = {} }] = useLazyQuery(PRODUCERS_QUERY, { variables }) const { data: dataHistory } = useSubscription(MISSED_BLOCKS_SUBSCRIPTION) const [loadStats, { loading = true, data: { eosrate_stats: stats } = {} }] = useLazyQuery(EOSRATE_STATS_QUERY) const [items, setItems] = useState([]) const [missedBlocks, setMissedBlocks] = useState({}) - + const [ + { filters, pagination }, + { handleOnSearch, handleOnPageChange, setPagination }, + ] = useSearchState({ loadProducers, info, variables, setVariables }) + useEffect(() => { loadStats({}) }, [loadStats]) diff --git a/webapp/src/hooks/customHooks/useEndpointsState.js b/webapp/src/hooks/customHooks/useEndpointsState.js index ee1f8422..0ddf02a8 100644 --- a/webapp/src/hooks/customHooks/useEndpointsState.js +++ b/webapp/src/hooks/customHooks/useEndpointsState.js @@ -1,21 +1,34 @@ import { useState, useEffect, useCallback } from 'react' -import { useSubscription } from '@apollo/client' +import { useSubscription, useLazyQuery } from '@apollo/client' -import { PRODUCERS_QUERY, ENDPOINTS_SUBSCRIPTION } from '../../gql' +import { ENDPOINTS_SUBSCRIPTION, PRODUCERS_COUNT_QUERY } from '../../gql' import useSearchState from './useSearchState' const useEndpointsState = () => { + const defaultVariables = { + limit: 20, + offset: 0, + endpointFilter: undefined, + where: { + owner: { _like: '%%' }, + nodes: { endpoints: { value: { _gt: '' } } }, + }, + } + const [variables, setVariables] = useState(defaultVariables) + const [loadProducers, { data: { info } = {} }] = useLazyQuery(PRODUCERS_COUNT_QUERY) + const { data, loading } = useSubscription(ENDPOINTS_SUBSCRIPTION, { variables }) + const [items, setItems] = useState() + const [ - { filters, pagination, variables }, + { filters, pagination }, { handleOnSearch, handleOnPageChange, setPagination }, ] = useSearchState({ - query: PRODUCERS_QUERY, - where: { nodes: { endpoints: { value: { _gt: '' } } } }, - limit: 20, + loadProducers, + info, + variables, + setVariables, }) - const { data, loading } = useSubscription(ENDPOINTS_SUBSCRIPTION, { variables }) - const [items, setItems] = useState() useEffect(() => { if (!data) return @@ -42,7 +55,7 @@ const useEndpointsState = () => { } }), ) - }, [data]) + }, [data, info]) const handleFilter = useCallback(value => { const filter = value @@ -58,7 +71,12 @@ const useEndpointsState = () => { }, [setPagination]) return [ - { loading, pagination, producers: items, filters }, + { + loading: loading && !items?.length, + pagination, + producers: items, + filters, + }, { handleFilter, handleOnPageChange, handleOnSearch, setPagination }, ] } diff --git a/webapp/src/hooks/customHooks/useNodeState.js b/webapp/src/hooks/customHooks/useNodeState.js index 02181fd1..8f4d1e50 100644 --- a/webapp/src/hooks/customHooks/useNodeState.js +++ b/webapp/src/hooks/customHooks/useNodeState.js @@ -1,21 +1,36 @@ import { useState, useEffect } from 'react' -import { useSubscription } from '@apollo/client' +import { useSubscription, useLazyQuery } from '@apollo/client' -import { PRODUCERS_QUERY, NODES_SUBSCRIPTION } from '../../gql' +import { NODES_SUBSCRIPTION, PRODUCERS_COUNT_QUERY } from '../../gql' import { eosConfig } from '../../config' import useSearchState from './useSearchState' const useNodeState = () => { + const defaultVariables = { + limit: 28, + offset: 0, + endpointFilter: undefined, + where: { + owner: { _like: '%%' }, + nodes: { type: { _neq: [] } }, + }, + } + const [variables, setVariables] = useState(defaultVariables) + const [loadProducers, { data: { info } = {} }] = useLazyQuery( + PRODUCERS_COUNT_QUERY, + ) + const { data, loading } = useSubscription(NODES_SUBSCRIPTION, { variables }) + const [items, setItems] = useState([]) const [ - { filters, pagination, variables }, + { filters, pagination }, { handleOnSearch, handleOnPageChange, setPagination }, ] = useSearchState({ - query: PRODUCERS_QUERY, - where: { nodes: { type: { _neq: [] } } }, + loadProducers, + info, + variables, + setVariables, }) - const { data, loading } = useSubscription(NODES_SUBSCRIPTION, { variables }) - const [items, setItems] = useState([]) const chips = [{ name: 'all' }, ...eosConfig.nodeChips] diff --git a/webapp/src/hooks/customHooks/useSearchState.js b/webapp/src/hooks/customHooks/useSearchState.js index c99639da..7ccd7ede 100644 --- a/webapp/src/hooks/customHooks/useSearchState.js +++ b/webapp/src/hooks/customHooks/useSearchState.js @@ -1,27 +1,14 @@ import { useState, useEffect, useCallback } from 'react' -import { useLazyQuery } from '@apollo/client' import { useLocation } from 'react-router-dom' import queryString from 'query-string' -const useSearchState = ({ query, where, limit }) => { - const [loadProducers, { loading = true, data: { producers, info } = {} }] = - useLazyQuery(query) +const useSearchState = ({ loadProducers, info, variables, setVariables }) => { const location = useLocation() - const defaultVariables = { - limit: limit ?? 28, - offset: 0, - endpointFilter: undefined, - where: { - owner: { _like: '%%' }, - ...(where ?? { bp_json: { _is_null: false } }), - } - } const [pagination, setPagination] = useState({ page: 1, pages: 1, - ...defaultVariables + ...variables, }) - const [variables, setVariables] = useState(defaultVariables) const [filters, setFilters] = useState({ name: 'all', owner: '' }) const handleOnSearch = useCallback(newFilters => { @@ -47,16 +34,15 @@ const useSearchState = ({ query, where, limit }) => { useEffect(() => { const variables = { - where: pagination.where, - offset: (pagination.page - 1) * pagination.limit, limit: pagination.limit, + offset: (pagination.page - 1) * pagination.limit, endpointFilter: pagination.endpointFilter, + where: pagination.where, } - loadProducers({ variables }) + loadProducers({ variables: { where: pagination.where } }) setVariables(variables) - // eslint-disable-next-line }, [ pagination.where, pagination.page, @@ -64,6 +50,7 @@ const useSearchState = ({ query, where, limit }) => { pagination.offset, pagination.endpointFilter, setVariables, + loadProducers, ]) useEffect(() => { @@ -78,6 +65,7 @@ const useSearchState = ({ query, where, limit }) => { })) setFilters(prev => ({ ...prev, owner: params.owner })) + // eslint-disable-next-line }, [location.search]) useEffect(() => { @@ -87,16 +75,15 @@ const useSearchState = ({ query, where, limit }) => { ...prev, pages: prev.limit ? Math.ceil(info.producers?.count / prev.limit) : 1, })) - }, [info]) + }, [info, pagination.limit]) return [ - { filters, pagination, loading, producers, info, variables }, + { filters, pagination }, { handleOnSearch, handleOnPageChange, setFilters, setPagination, - loadProducers, }, ] } diff --git a/webapp/src/language/en.json b/webapp/src/language/en.json index 5dc41b2b..de6f7201 100644 --- a/webapp/src/language/en.json +++ b/webapp/src/language/en.json @@ -365,8 +365,6 @@ "endpointsListRoute": { "title": "Endpoints available by", "endpointsResponding": "Only endpoints responding", - "showList": "Show List", - "listOfResponding": "List of endpoints that are responding", "linkToStats": "Go to stats", "filterEndpoints": "Filter responding endpoints" }, diff --git a/webapp/src/language/es.json b/webapp/src/language/es.json index 41d2c6ea..a9218ce0 100644 --- a/webapp/src/language/es.json +++ b/webapp/src/language/es.json @@ -364,8 +364,6 @@ "title": "Endpoints disponibles por", "updatedAt": "Actualizado por última vez", "endpointsResponding": "Solo puntos finales que responden", - "showList": "Ver la lista", - "listOfResponding": "Lista de los puntos finales que responden", "linkToStats": "Ir a estadísticas", "filterEndpoints": "Filtrar puntos finales" }, diff --git a/webapp/src/routes/EndpointsList/index.js b/webapp/src/routes/EndpointsList/index.js index cfc42a07..59ecba10 100644 --- a/webapp/src/routes/EndpointsList/index.js +++ b/webapp/src/routes/EndpointsList/index.js @@ -32,7 +32,7 @@ const EndpointsList = () => { const [ { loading, pagination, producers, filters }, { handleFilter, handleOnSearch, handleOnPageChange, setPagination }, - ] = useEndpointsState({ useCache: false }) + ] = useEndpointsState() return ( From 3ee9586a2ecf39378d7389a8823fcd73ba03332a Mon Sep 17 00:00:00 2001 From: Torresmorah Date: Mon, 11 Sep 2023 10:31:59 -0600 Subject: [PATCH 05/10] chore(webapp): get list to copy from useEndpointsState --- .../src/components/CopyToClipboard/index.js | 1 + webapp/src/components/EndpointsTable/index.js | 54 +++--------------- webapp/src/gql/producer.gql.js | 18 ------ .../hooks/customHooks/useEndpointsState.js | 57 ++++++++++++++++--- webapp/src/routes/EndpointsList/index.js | 6 +- 5 files changed, 59 insertions(+), 77 deletions(-) diff --git a/webapp/src/components/CopyToClipboard/index.js b/webapp/src/components/CopyToClipboard/index.js index 491fea0d..08ccedc3 100644 --- a/webapp/src/components/CopyToClipboard/index.js +++ b/webapp/src/components/CopyToClipboard/index.js @@ -32,6 +32,7 @@ const CopyToClipboard = ({ text }) => { variant="outlined" color="primary" onClick={copyText} + disabled={!text} className={classes.icon} startIcon={} > diff --git a/webapp/src/components/EndpointsTable/index.js b/webapp/src/components/EndpointsTable/index.js index 919cae1d..5a226782 100644 --- a/webapp/src/components/EndpointsTable/index.js +++ b/webapp/src/components/EndpointsTable/index.js @@ -1,5 +1,4 @@ -import React, { useState, useEffect } from 'react' -import { useLazyQuery } from '@apollo/client' +import React from 'react' import PropTypes from 'prop-types' import { useTranslation } from 'react-i18next' import { makeStyles } from '@mui/styles' @@ -19,54 +18,14 @@ import CopyToClipboard from '../CopyToClipboard' import HealthCheck from '../HealthCheck' import HealthCheckInfo from '../HealthCheck/HealthCheckInfo' import { getStatus } from 'utils' -import { ENDPOINTS_QUERY } from '../../gql' import styles from './styles' const useStyles = makeStyles(styles) -const EndpointsTable = ({ producers }) => { +const EndpointsTable = ({ producers, textLists }) => { const classes = useStyles() const { t } = useTranslation('endpointsListRoute') - const [textLists, setTextLists] = useState({}) - const [loadProducers, { data: { producers: bpsWorkingEndpoints } = {} }] = - useLazyQuery(ENDPOINTS_QUERY) - - useEffect(()=>{ - loadProducers({ - variables: { - where: { - response: { _contains: { isWorking: true } }, - }, - }, - }) - },[loadProducers]) - - useEffect(() => { - if (!bpsWorkingEndpoints?.length) return - - let endpointsList = {api:'',p2p:'',ssl:''} - - Object.keys(endpointsList).forEach(type => { - endpointsList[type] += `# List of available ${type.toUpperCase()} endpoints \n` - - bpsWorkingEndpoints.forEach(producer => { - if (!!producer?.endpoints?.length && producer.endpoints.some(endpoint=>endpoint.type===type)) { - endpointsList[type] += `# ${producer.owner} \n` - producer.endpoints.forEach(endpoint => { - if (endpoint.type === type) { - endpointsList[type] += `${type === 'p2p' ? 'p2p-peer-address = ' : ''} ${ - endpoint.value - } \n` - } - }) - endpointsList[type] += '\n' - } - }) - }) - - setTextLists(endpointsList) - }, [bpsWorkingEndpoints]) const CellList = ({ producer, endpointType }) => { return ( @@ -100,19 +59,19 @@ const EndpointsTable = ({ producers }) => {
{t('api')} - -
+ +
{t('ssl')} - +
{t('p2p')} - +
@@ -153,6 +112,7 @@ const EndpointsTable = ({ producers }) => { EndpointsTable.propTypes = { producers: PropTypes.array, + textLists: PropTypes.object, } export default EndpointsTable diff --git a/webapp/src/gql/producer.gql.js b/webapp/src/gql/producer.gql.js index 786fc0d7..1e17debe 100644 --- a/webapp/src/gql/producer.gql.js +++ b/webapp/src/gql/producer.gql.js @@ -109,24 +109,6 @@ export const ENDPOINTS_SUBSCRIPTION = gql` } ` -export const ENDPOINTS_QUERY = gql` - query producer( - $where: endpoints_by_producer_id_bool_exp! - ) { - producers: producer( - where: {endpoints_list: {_and: [{type: {_gt: ""}}, $where]}} - order_by: { total_votes_percent: desc } - ) { - id - owner - endpoints: endpoints_list(where: $where) { - type - value - } - } - } -` - export const NODE_CPU_BENCHMARK = gql` query ($account: String) { cpu( diff --git a/webapp/src/hooks/customHooks/useEndpointsState.js b/webapp/src/hooks/customHooks/useEndpointsState.js index 0ddf02a8..2bf0a7e2 100644 --- a/webapp/src/hooks/customHooks/useEndpointsState.js +++ b/webapp/src/hooks/customHooks/useEndpointsState.js @@ -19,6 +19,7 @@ const useEndpointsState = () => { const [loadProducers, { data: { info } = {} }] = useLazyQuery(PRODUCERS_COUNT_QUERY) const { data, loading } = useSubscription(ENDPOINTS_SUBSCRIPTION, { variables }) const [items, setItems] = useState() + const [textLists, setTextLists] = useState() const [ { filters, pagination }, @@ -33,27 +34,64 @@ const useEndpointsState = () => { useEffect(() => { if (!data) return - setItems( - data.producers.map((producer) => { + const { newItems, workingEndpoints } = data.producers.reduce( + (state, producer) => { const endpoints = { api: [], ssl: [], p2p: [] } const inserted = [] + const bpName = + producer.bp_json?.org?.candidate_name || + producer?.bp_json?.org?.organization_name || + producer?.owner + producer.endpoints.forEach(({ type, ...endpoint }) => { if (!inserted.includes(endpoint.value)) { inserted.push(endpoint.value) endpoints[type].push(endpoint) + + if (endpoint?.response?.isWorking) { + state.workingEndpoints[type].push({ + value: endpoint.value, + name: bpName, + }) + } } }) - return { + state.newItems.push({ id: producer.id, - name: - producer.bp_json?.org?.candidate_name || - producer?.bp_json?.org?.organization_name || - producer?.owner, + name: bpName, endpoints, - } - }), + }) + + return state + }, + { newItems: [], workingEndpoints: { api: [], ssl: [], p2p: [] } }, + ) + + setItems(newItems) + + setTextLists( + Object.keys(workingEndpoints).reduce((state, type) => { + let previous = '' + let endpointsList = '' + + workingEndpoints[type].forEach(({ value, name }, index) => { + endpointsList += !index + ? `# List of available ${type.toUpperCase()} endpoints \n` + : '' + + endpointsList += previous !== name ? `# ${name} \n` : '' + endpointsList += `${ + type === 'p2p' ? 'p2p-peer-address = ' : '' + } ${value} \n` + endpointsList += '\n' + + previous = name + }) + + return { ...state, [type]: endpointsList } + }, {}), ) }, [data, info]) @@ -75,6 +113,7 @@ const useEndpointsState = () => { loading: loading && !items?.length, pagination, producers: items, + textLists, filters, }, { handleFilter, handleOnPageChange, handleOnSearch, setPagination }, diff --git a/webapp/src/routes/EndpointsList/index.js b/webapp/src/routes/EndpointsList/index.js index 59ecba10..5f3644ad 100644 --- a/webapp/src/routes/EndpointsList/index.js +++ b/webapp/src/routes/EndpointsList/index.js @@ -24,13 +24,13 @@ import styles from './styles' const useStyles = makeStyles(styles) -const limitOptions = [10, 20, 30, 50, 80, 130] +const limitOptions = [10, 20, 30, 50, 80, 150] const EndpointsList = () => { const classes = useStyles() const { t } = useTranslation('endpointsListRoute') const [ - { loading, pagination, producers, filters }, + { loading, pagination, producers, textLists, filters }, { handleFilter, handleOnSearch, handleOnPageChange, setPagination }, ] = useEndpointsState() @@ -95,7 +95,7 @@ const EndpointsList = () => { ) : ( <> {!!producers?.length ? ( - + ) : (
From 8d60995fbab98292f64fc26e50376024859e5c8b Mon Sep 17 00:00:00 2001 From: Torresmorah Date: Mon, 11 Sep 2023 10:48:09 -0600 Subject: [PATCH 06/10] chore(webapp): add a better helper text for copy button --- webapp/src/components/CopyToClipboard/index.js | 7 ++++--- webapp/src/components/CopyToClipboard/styles.js | 7 +++++++ webapp/src/components/EndpointsTable/index.js | 6 +++--- webapp/src/language/en.json | 3 ++- webapp/src/language/es.json | 5 +++-- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/webapp/src/components/CopyToClipboard/index.js b/webapp/src/components/CopyToClipboard/index.js index 08ccedc3..203a8f24 100644 --- a/webapp/src/components/CopyToClipboard/index.js +++ b/webapp/src/components/CopyToClipboard/index.js @@ -9,7 +9,7 @@ import styles from './styles' const useStyles = makeStyles(styles) -const CopyToClipboard = ({ text }) => { +const CopyToClipboard = ({ text, helperText }) => { const classes = useStyles() const { t } = useTranslation('copyToClipboardComponent') const [status, setStatus] = useState('copyToClipboard') @@ -21,11 +21,12 @@ const CopyToClipboard = ({ text }) => { return ( { setStatus('copyToClipboard') }} - arrow + classes={{ popper: classes.tooltip }} >
diff --git a/webapp/src/language/en.json b/webapp/src/language/en.json index c1bed97d..46622ecb 100644 --- a/webapp/src/language/en.json +++ b/webapp/src/language/en.json @@ -395,7 +395,7 @@ "status": "Status", "response": "Response", "headBlockTime": "Head Block Time", - "updatedAt": "Updated at", + "updatedAt": "Last check", "error": "Error", "noResponse": "No response" }, diff --git a/webapp/src/language/es.json b/webapp/src/language/es.json index feadaecd..6b01f24d 100644 --- a/webapp/src/language/es.json +++ b/webapp/src/language/es.json @@ -394,7 +394,7 @@ "status": "Estado", "response": "Respuesta", "headBlockTime": "Fecha del último bloque", - "updatedAt": "Actualizado por última vez", + "updatedAt": "Comprobado por última vez", "error": "Error", "noResponse": "Sin respuesta", "Bad Gateway": "Mal puerta de enlace", diff --git a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js index 7d00a94f..8a1940e8 100644 --- a/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js +++ b/webapp/src/routes/EVMEndpointsList/useRPCEndpointsState.js @@ -77,10 +77,12 @@ const useRPCEndpointsState = () => { setEndpoints(prev => prev.map(endpoint => ({ url: endpoint.url, response: {} }))) const rpcList = JSON.parse(JSON.stringify(endpoints)) + let checked = 0 rpcList.forEach(async ({ url }, index) => { const endpoint = await getEndpointHealthCheck(url) + checked += 1 setEndpoints(prev => { const newEndpoints = [ ...prev.slice(0, index), @@ -88,7 +90,10 @@ const useRPCEndpointsState = () => { ...prev.slice(index + 1), ] - if (newEndpoints.every(endpoint => !!endpoint.response.statusText)) { + if ( + newEndpoints.length === checked || + newEndpoints.every(endpoint => !!endpoint.response.statusText) + ) { newEndpoints.sort((e1, e2) => e1?.height === e2?.height ? e1?.latency - e2?.latency From 577089efa7ba29304fd735c52f4aed81fec58c83 Mon Sep 17 00:00:00 2001 From: codefactor-io Date: Mon, 11 Sep 2023 20:53:50 +0000 Subject: [PATCH 09/10] [CodeFactor] Apply fixes --- webapp/src/hooks/customHooks/useBlockProducerState.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webapp/src/hooks/customHooks/useBlockProducerState.js b/webapp/src/hooks/customHooks/useBlockProducerState.js index d00c83a8..3acb8081 100644 --- a/webapp/src/hooks/customHooks/useBlockProducerState.js +++ b/webapp/src/hooks/customHooks/useBlockProducerState.js @@ -45,8 +45,8 @@ const useBlockProducerState = () => { const [ { filters, pagination }, { handleOnSearch, handleOnPageChange, setPagination }, - ] = useSearchState({ loadProducers, info, variables, setVariables }) - + ] = useSearchState({ loadProducers, info, variables, setVariables }) + useEffect(() => { loadStats({}) }, [loadStats]) From 53db16959a1b9fee41ba4ee592873a121be364f6 Mon Sep 17 00:00:00 2001 From: Xavier Fernandez Date: Mon, 11 Sep 2023 21:51:18 -0600 Subject: [PATCH 10/10] feat(jungle): enable cpu benchmarks for jungle testnet --- .github/workflows/deploy-jungle-testnet.yaml | 3 ++- webapp/public/sitemap.jungle.xml | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy-jungle-testnet.yaml b/.github/workflows/deploy-jungle-testnet.yaml index 12217ce8..14fc580f 100644 --- a/.github/workflows/deploy-jungle-testnet.yaml +++ b/.github/workflows/deploy-jungle-testnet.yaml @@ -52,7 +52,7 @@ jobs: REACT_APP_SYNC_TOLERANCE_INTERVAL: 180000 REACT_APP_TOKEN_SYMBOL: 'EOS' REACT_APP_NETWORK_URL: '[{"label":"EOS","value":"https://eos.antelope.tools","mainnet":true,"pair":"eos","icon":"eos","order":5},{"label":"Proton","value":"https://proton.antelope.tools","mainnet":true,"pair":"proton","icon":"proton","order":3},{"label":"WAX","value":"https://wax.antelope.tools","mainnet":true,"pair":"wax","icon":"wax","order":4},{"label":"Telos","value":"https://telos.antelope.tools","mainnet":true,"pair":"telos","icon":"telos","order":1},{"label":"Libre","value":"https://libre.antelope.tools","mainnet":true,"pair":"libre","icon":"libre","order":2},{"label":"LACChain EOSIO","value":"https://lacchain.antelope.tools","mainnet":true,"pair":null,"icon":"lacchain","order":6},{"label":"Jungle4 Testnet","value":"https://jungle.antelope.tools","mainnet":false,"pair":"eos","icon":"jungle","order":5},{"label":"Proton Testnet","value":"https://proton-testnet.antelope.tools","mainnet":false,"pair":"proton","icon":"proton","order":3},{"label":"WAX Testnet","value":"https://wax-testnet.antelope.tools","mainnet":false,"pair":"wax","icon":"wax","order":4},{"label":"Telos Testnet","value":"https://telos-testnet.antelope.tools","mainnet":false,"pair":"telos","icon":"telos","order":1},{"label":"Libre Testnet","value":"https://libre-testnet.antelope.tools","mainnet":false,"pair":"libre","icon":"libre","order":2},{"label":"Ultra Testnet","value":"https://ultra-testnet.antelope.tools","mainnet":false,"pair":"ultra","icon":"ultra","order":6}]' - REACT_APP_DISABLED_MENU_ITEMS: '["/missed-blocks","/block-distribution","/cpu-benchmark","/stress-test","/evm","/evm-rpc-endpoints"]' + REACT_APP_DISABLED_MENU_ITEMS: '["/missed-blocks","/block-distribution","/stress-test","/evm","/evm-rpc-endpoints"]' REACT_APP_BLOCK_EXPLORER_URL: 'https://jungle4.eosq.eosnation.io/tx/(transaction)' REACT_APP_STATE_HISTORY_ENABLED: 'false' REACT_APP_GOOGLE_ANALITIC_PAGE_ID: 'G-E6Y0EC9FT8' @@ -83,6 +83,7 @@ jobs: HAPI_EOS_BASE_ACCOUNT: ${{ secrets.HAPI_EOS_BASE_ACCOUNT }} HAPI_EOS_BASE_ACCOUNT_PASSWORD: ${{ secrets.HAPI_EOS_BASE_ACCOUNT_PASSWORD }} HAPI_EOS_MECHANICS_ACCOUNT: ${{ secrets.HAPI_EOS_MECHANICS_ACCOUNT }} + HAPI_EOS_MECHANICS_CUSTOM_PERMISSION: 'benchmark' HAPI_EOS_MECHANICS_PASSWORD: ${{ secrets.HAPI_EOS_MECHANICS_PASSWORD }} HAPI_EOS_WALLET_URL: http://dashboard-wallet:8888 HAPI_EOS_BP_JSON_ON_CHAIN: false diff --git a/webapp/public/sitemap.jungle.xml b/webapp/public/sitemap.jungle.xml index d6ecb1fc..b1d13bc2 100644 --- a/webapp/public/sitemap.jungle.xml +++ b/webapp/public/sitemap.jungle.xml @@ -31,6 +31,10 @@ https://jungle.antelope.tools/undiscoverable-bps 2023-09-07 + + https://jungle.antelope.tools/cpu-benchmark + 2023-09-10 + https://jungle.antelope.tools/ricardian-contract 2023-09-07