fix (#1117): Network stats env (#1122)

* fix: explorer environment

* fix: stats env

* fix: format

* fix: remove logging
This commit is contained in:
botond 2022-08-25 22:46:17 +01:00 committed by GitHub
parent ad185651fb
commit 760a24b500
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 314 additions and 193 deletions

View File

@ -3,7 +3,6 @@ NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=CUSTOM NX_VEGA_ENV=CUSTOM
NX_VEGA_REST=http://localhost:3029
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm NX_TENDERMINT_URL=https://n01.stagnet3.vega.xyz/tm
@ -12,7 +11,6 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://n01.stagnet3.vega.xyz/query NX_VEGA_URL=https://n01.stagnet3.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3 NX_VEGA_ENV=STAGNET3
NX_VEGA_REST=https://n01.stagnet3.vega.xyz/datanode/rest
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
# App flags # App flags

View File

@ -5,7 +5,6 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=CUSTOM NX_VEGA_ENV=CUSTOM
NX_VEGA_REST=http://localhost:3029
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
# App flags # App flags

View File

@ -6,5 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_URL=https://n04.d.vega.xyz/query NX_VEGA_URL=https://n04.d.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -6,5 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_URL=https://api.token.vega.xyz/query NX_VEGA_URL=https://api.token.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -6,5 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
NX_VEGA_URL=https://n03.s.vega.xyz/query NX_VEGA_URL=https://n03.s.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=STAGNET NX_VEGA_ENV=STAGNET
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -6,5 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://n01.stagnet3.vega.xyz/query NX_VEGA_URL=https://n01.stagnet3.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3 NX_VEGA_ENV=STAGNET3
NX_VEGA_REST=https://n01.stagnet3.vega.xyz/datanode/rest
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -6,5 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}' NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://api.n11.testnet.vega.xyz
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -4,5 +4,4 @@ NX_TENDERMINT_URL=http://localhost:26607/
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_URL=http://localhost:3003/query NX_VEGA_URL=http://localhost:3003/query
NX_VEGA_ENV=CUSTOM NX_VEGA_ENV=CUSTOM
NX_VEGA_REST=http://localhost:3029/rest
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions

View File

@ -47,13 +47,12 @@ yarn nx run explorer:serve --env={env} # e.g. stagnet1
There are a few different configuration options offered for this app: There are a few different configuration options offered for this app:
| **Flag** | **Purpose** | | **Flag** | **Purpose** |
| -------------------------------- | ---------------------------------------------------------------------------------------------------- | | -------------------------------- | ---------------------------------------------------------------------------------------------------- | --- |
| `NX_CHAIN_EXPLORER_URL` | The URL of the chain explorer service for decoding transactions | | `NX_CHAIN_EXPLORER_URL` | The URL of the chain explorer service for decoding transactions |
| `NX_TENDERMINT_URL` | The Tendermint REST URL for the Vega consesus engine | | `NX_TENDERMINT_URL` | The Tendermint REST URL for the Vega consesus engine |
| `NX_TENDERMINT_WEBSOCKET_URL` | The Tendermint Websocket URL for the Vega consensus engine | | `NX_TENDERMINT_WEBSOCKET_URL` | The Tendermint Websocket URL for the Vega consensus engine |
| `NX_VEGA_URL` | The GraphQl query endpoint of a [Vega data node](https://github.com/vegaprotocol/networks#data-node) | | `NX_VEGA_URL` | The GraphQl query endpoint of a [Vega data node](https://github.com/vegaprotocol/networks#data-node) |
| `NX_VEGA_ENV` | The name of the currently connected vega environment | | `NX_VEGA_ENV` | The name of the currently connected vega environment | |
| `NX_VEGA_REST` | The REST URL for the Vega Data Node |
| `NX_EXPLORER_ASSETS` | Enable the assets page for the explorer | | `NX_EXPLORER_ASSETS` | Enable the assets page for the explorer |
| `NX_EXPLORER_GENESIS` | Enable the genesis page for the explorer | | `NX_EXPLORER_GENESIS` | Enable the genesis page for the explorer |
| `NX_EXPLORER_GOVERNANCE` | Enable the governance page for the explorer | | `NX_EXPLORER_GOVERNANCE` | Enable the governance page for the explorer |

View File

@ -1,15 +1,23 @@
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { useLocation } from 'react-router-dom'; import { useLocation } from 'react-router-dom';
import { ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers'; import { ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment'; import {
EnvironmentProvider,
NetworkLoader,
useEnvironment,
} from '@vegaprotocol/environment';
import { NetworkInfo } from '@vegaprotocol/network-info'; import { NetworkInfo } from '@vegaprotocol/network-info';
import { createClient } from './lib/apollo-client'; import { createClient } from './lib/apollo-client';
import { Nav } from './components/nav'; import { Nav } from './components/nav';
import { Header } from './components/header'; import { Header } from './components/header';
import { Main } from './components/main'; import { Main } from './components/main';
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider'; import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import { ENV } from './config/env';
function App() { function App() {
const { VEGA_ENV } = useEnvironment();
const [theme, toggleTheme] = useThemeSwitcher(); const [theme, toggleTheme] = useThemeSwitcher();
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
@ -19,8 +27,16 @@ function App() {
setMenuOpen(false); setMenuOpen(false);
}, [location]); }, [location]);
useEffect(() => {
Sentry.init({
dsn: ENV.dsn,
integrations: [new BrowserTracing()],
tracesSampleRate: 1,
environment: VEGA_ENV,
});
}, [VEGA_ENV]);
return ( return (
<EnvironmentProvider>
<ThemeContext.Provider value={theme}> <ThemeContext.Provider value={theme}>
<TendermintWebsocketProvider> <TendermintWebsocketProvider>
<NetworkLoader createClient={createClient}> <NetworkLoader createClient={createClient}>
@ -45,8 +61,15 @@ function App() {
</NetworkLoader> </NetworkLoader>
</TendermintWebsocketProvider> </TendermintWebsocketProvider>
</ThemeContext.Provider> </ThemeContext.Provider>
</EnvironmentProvider>
); );
} }
export default App; const Wrapper = () => {
return (
<EnvironmentProvider>
<App />
</EnvironmentProvider>
);
};
export default Wrapper;

View File

@ -11,13 +11,10 @@ export const ENV = {
// Data sources // Data sources
// Environment // Environment
dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'), dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'),
envName: windowOrDefault('NX_VEGA_ENV'),
dataSources: { dataSources: {
chainExplorerUrl: windowOrDefault('NX_CHAIN_EXPLORER_URL'), chainExplorerUrl: windowOrDefault('NX_CHAIN_EXPLORER_URL'),
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'), tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'), tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
dataNodeUrl: windowOrDefault('NX_VEGA_URL'),
restEndpoint: windowOrDefault('NX_VEGA_REST'),
}, },
flags: { flags: {
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')), assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),

View File

@ -1,21 +1,10 @@
import { DATA_SOURCES } from '../../config';
import { StatsManager } from '@vegaprotocol/network-stats'; import { StatsManager } from '@vegaprotocol/network-stats';
import { ENV } from '../../config/env';
const envName = ENV.envName;
const restEndpoint = DATA_SOURCES.restEndpoint;
const statsEndpoint = `${restEndpoint}/statistics`;
const nodesEndpoint = `${restEndpoint}/nodes-data`;
const Home = () => { const Home = () => {
const classnames = 'mt-12 grid grid-cols-1 lg:grid-cols-2 lg:gap-16';
return ( return (
<section> <section>
<StatsManager <StatsManager className={classnames} />
envName={envName}
statsEndpoint={statsEndpoint}
nodesEndpoint={nodesEndpoint}
className="mt-12 grid grid-cols-1 lg:grid-cols-2 lg:gap-16"
/>
</section> </section>
); );
}; };

View File

@ -1,24 +1,10 @@
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { createRoot } from 'react-dom/client'; import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import './styles.css'; import './styles.css';
import App from './app/app'; import App from './app/app';
import { ENV } from './app/config/env';
import { StrictMode } from 'react'; import { StrictMode } from 'react';
const { dsn } = ENV;
/* istanbul ignore next */
if (dsn) {
Sentry.init({
dsn,
integrations: [new BrowserTracing()],
tracesSampleRate: 1,
environment: ENV.envName,
});
}
const rootElement = document.getElementById('root'); const rootElement = document.getElementById('root');
const root = rootElement && createRoot(rootElement); const root = rootElement && createRoot(rootElement);

View File

@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/ NX_VEGA_URL=https://api.token.vega.xyz/query

View File

@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://n04.d.vega.xyz/datanode/rest NX_VEGA_URL=https://n04.d.vega.xyz/query

View File

@ -1,3 +1,3 @@
# App configuration variables. No overrides for default urls # App configuration variables. No overrides for default urls
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz/ NX_VEGA_URL=https://api.token.vega.xyz/query

View File

@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=STAGNET1; NX_VEGA_ENV=STAGNET1;
NX_VEGA_REST=https://n03.s.vega.xyz/datanode/rest; NX_VEGA_URL=https://n03.s.vega.xyz/query;

View File

@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_REST=https://n01.stagnet3.vega.xyz/datanode/rest; NX_VEGA_URL=https://n01.stagnet3.vega.xyz/query;
NX_VEGA_ENV=STAGNET3; NX_VEGA_ENV=STAGNET3;

View File

@ -1,3 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://api.n11.testnet.vega.xyz NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql

View File

@ -1,33 +1,33 @@
import React from 'react'; import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
import { DATA_SOURCES } from './config';
import { Header } from './components/header'; import { Header } from './components/header';
import { StatsManager } from '@vegaprotocol/network-stats'; import { StatsManager } from '@vegaprotocol/network-stats';
import { ThemeContext } from '@vegaprotocol/react-helpers'; import { ThemeContext } from '@vegaprotocol/react-helpers';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers'; import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { createClient } from './lib/apollo-client';
const envName = DATA_SOURCES.envName;
const restEndpoint = DATA_SOURCES.restEndpoint;
const statsEndpoint = `${restEndpoint}/statistics`;
const nodesEndpoint = `${restEndpoint}/nodes-data`;
function App() { function App() {
const [theme, toggleTheme] = useThemeSwitcher(); const [theme, toggleTheme] = useThemeSwitcher();
return ( return (
<ThemeContext.Provider value={theme}> <ThemeContext.Provider value={theme}>
<NetworkLoader createClient={createClient}>
<div className="w-screen min-h-screen grid pb-24 bg-white text-black-95 dark:bg-black dark:text-white-80"> <div className="w-screen min-h-screen grid pb-24 bg-white text-black-95 dark:bg-black dark:text-white-80">
<div className="layout-grid w-screen justify-self-center"> <div className="layout-grid w-screen justify-self-center">
<Header toggleTheme={toggleTheme} /> <Header toggleTheme={toggleTheme} />
<StatsManager <StatsManager className="max-w-3xl px-24" />
envName={envName}
statsEndpoint={statsEndpoint}
nodesEndpoint={nodesEndpoint}
className="max-w-3xl px-24"
/>
</div> </div>
</div> </div>
</NetworkLoader>
</ThemeContext.Provider> </ThemeContext.Provider>
); );
} }
export default App; const Wrapper = () => {
return (
<EnvironmentProvider>
<App />
</EnvironmentProvider>
);
};
export default Wrapper;

View File

@ -1,4 +0,0 @@
export const DATA_SOURCES = {
envName: process.env['NX_VEGA_ENV'] as string,
restEndpoint: process.env['NX_VEGA_REST'] as string,
};

View File

@ -0,0 +1,52 @@
import { ApolloClient, from, HttpLink, InMemoryCache } from '@apollo/client';
import { onError } from '@apollo/client/link/error';
import { RetryLink } from '@apollo/client/link/retry';
export function createClient(base?: string) {
if (!base) {
throw new Error('Base must be passed into createClient!');
}
const urlHTTP = new URL(base);
const urlWS = new URL(base);
// Replace http with ws, preserving if its a secure connection eg. https => wss
urlWS.protocol = urlWS.protocol.replace('http', 'ws');
const cache = new InMemoryCache({
typePolicies: {
Query: {},
Account: {
keyFields: false,
fields: {
balanceFormatted: {},
},
},
Node: {
keyFields: false,
},
},
});
const retryLink = new RetryLink({
delay: {
initial: 300,
max: 10000,
jitter: true,
},
});
const httpLink = new HttpLink({
uri: urlHTTP.href,
credentials: 'same-origin',
});
const errorLink = onError(({ graphQLErrors, networkError }) => {
console.log(graphQLErrors);
console.log(networkError);
});
return new ApolloClient({
connectToDevTools: process.env['NODE_ENV'] === 'development',
link: from([errorLink, retryLink, httpLink]),
cache,
});
}

View File

@ -18,7 +18,7 @@ const compileHosts = (hosts: string[], envUrl?: string) => {
const getCacheKey = (env: Networks) => `${LOCAL_STORAGE_NETWORK_KEY}-${env}`; const getCacheKey = (env: Networks) => `${LOCAL_STORAGE_NETWORK_KEY}-${env}`;
const getCachedConfig = (env: Networks) => { const getCachedConfig = (env: Networks, envUrl?: string) => {
const cacheKey = getCacheKey(env); const cacheKey = getCacheKey(env);
const value = LocalStorage.getItem(cacheKey); const value = LocalStorage.getItem(cacheKey);
@ -31,7 +31,10 @@ const getCachedConfig = (env: Networks) => {
throw new Error('Invalid configuration found in the storage.'); throw new Error('Invalid configuration found in the storage.');
} }
return config; return {
...config,
hosts: compileHosts(config.hosts, envUrl),
};
} catch (err) { } catch (err) {
LocalStorage.removeItem(cacheKey); LocalStorage.removeItem(cacheKey);
console.warn( console.warn(
@ -49,7 +52,7 @@ export const useConfig = (
) => { ) => {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [config, setConfig] = useState<Configuration | undefined>( const [config, setConfig] = useState<Configuration | undefined>(
getCachedConfig(environment.VEGA_ENV) getCachedConfig(environment.VEGA_ENV, environment.VEGA_URL)
); );
useEffect(() => { useEffect(() => {

View File

@ -110,11 +110,10 @@ export const getErrorByType = (
}; };
export const getErrorType = (env: Networks, data?: NodeData) => { export const getErrorType = (env: Networks, data?: NodeData) => {
if (data && !getIsNodeLoading(data) && data.initialized) { if (data && data.initialized) {
if (getIsInvalidUrl(data.url)) { if (getIsInvalidUrl(data.url)) {
return ErrorType.INVALID_URL; return ErrorType.INVALID_URL;
} }
if ( if (
data.chain.hasError || data.chain.hasError ||
data.responseTime.hasError || data.responseTime.hasError ||
@ -123,7 +122,7 @@ export const getErrorType = (env: Networks, data?: NodeData) => {
return ErrorType.CONNECTION_ERROR; return ErrorType.CONNECTION_ERROR;
} }
if (getHasInvalidChain(env, data.chain.value)) { if (!data.chain.isLoading && getHasInvalidChain(env, data.chain.value)) {
return ErrorType.INVALID_NETWORK; return ErrorType.INVALID_NETWORK;
} }

View File

@ -1,6 +1,6 @@
{ {
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"], "extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*"], "ignorePatterns": ["!**/*", "__generated__"],
"overrides": [ "overrides": [
{ {
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"], "files": ["*.ts", "*.tsx", "*.js", "*.jsx"],

View File

@ -0,0 +1,95 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
// ====================================================
// GraphQL query operation: NetworkStats
// ====================================================
export interface NetworkStats_nodeData {
__typename: "NodeData";
/**
* Total staked amount across all nodes
*/
stakedTotal: string;
/**
* Total number of nodes
*/
totalNodes: number;
/**
* Number of inactive nodes
*/
inactiveNodes: number;
/**
* Number of nodes validating
*/
validatingNodes: number;
/**
* Total uptime for all epochs across all nodes. Or specify a number of epochs
*/
uptime: number;
}
export interface NetworkStats_statistics {
__typename: "Statistics";
/**
* Status of the Vega application connection with the chain
*/
status: string;
/**
* Current block number
*/
blockHeight: string;
/**
* Duration of the last block, in nanoseconds
*/
blockDuration: string;
/**
* Number of items in the backlog
*/
backlogLength: string;
/**
* Number of transaction processed per block
*/
txPerBlock: string;
/**
* Number of the trades per seconds
*/
tradesPerSecond: string;
/**
* Number of orders per seconds
*/
ordersPerSecond: string;
/**
* Average number of orders added per blocks
*/
averageOrdersPerBlock: string;
/**
* RFC3339Nano current time of the chain (decided through consensus)
*/
vegaTime: string;
/**
* Version of the Vega node (semver)
*/
appVersion: string;
/**
* Version of the chain (semver)
*/
chainVersion: string;
/**
* Current chain ID
*/
chainId: string;
}
export interface NetworkStats {
/**
* returns information about nodes
*/
nodeData: NetworkStats_nodeData | null;
/**
* get statistics about the Vega node
*/
statistics: NetworkStats_statistics;
}

View File

@ -1,5 +1,7 @@
import { useEffect, useState } from 'react'; import { useEffect } from 'react';
import classnames from 'classnames'; import classnames from 'classnames';
import { useQuery, gql } from '@apollo/client';
import { useEnvironment } from '@vegaprotocol/environment';
import { statsFields } from '../../config/stats-fields'; import { statsFields } from '../../config/stats-fields';
import type { import type {
Stats as IStats, Stats as IStats,
@ -9,43 +11,45 @@ import { Table } from '../table';
import { TableRow } from '../table-row'; import { TableRow } from '../table-row';
import { PromotedStats } from '../promoted-stats'; import { PromotedStats } from '../promoted-stats';
import { PromotedStatsItem } from '../promoted-stats-item'; import { PromotedStatsItem } from '../promoted-stats-item';
import type { NetworkStats } from './__generated__/NetworkStats';
interface StatsManagerProps { interface StatsManagerProps {
envName: string;
statsEndpoint: string;
nodesEndpoint: string;
className?: string; className?: string;
} }
export const StatsManager = ({ const STATS_QUERY = gql`
envName, query NetworkStats {
statsEndpoint, nodeData {
nodesEndpoint, stakedTotal
className, totalNodes
}: StatsManagerProps) => { inactiveNodes
const [data, setData] = useState<IStructuredStats | null>(null); validatingNodes
const [error, setError] = useState<Error | null>(null); uptime
useEffect(() => {
async function getStats() {
try {
const [res1, res2] = await Promise.all([
fetch(statsEndpoint),
fetch(nodesEndpoint),
]);
const [{ statistics }, { nodeData }] = await Promise.all([
res1.json(),
res2.json(),
]);
const returned = { ...nodeData, ...statistics };
if (!statistics || !nodeData) {
throw new Error('Failed to get data from endpoints');
} }
statistics {
status
blockHeight
blockDuration
backlogLength
txPerBlock
tradesPerSecond
ordersPerSecond
averageOrdersPerBlock
vegaTime
appVersion
chainVersion
chainId
}
}
`;
const compileData = (data?: NetworkStats) => {
const { nodeData, statistics } = data || {};
const returned = { ...nodeData, ...statistics };
// Loop through the stats fields config, grabbing values from the fetched // Loop through the stats fields config, grabbing values from the fetched
// data and building a set of promoted and standard table entries. // data and building a set of promoted and standard table entries.
const structured = Object.entries(statsFields).reduce( return Object.entries(statsFields).reduce(
(acc, [key, value]) => { (acc, [key, value]) => {
const statKey = key as keyof IStats; const statKey = key as keyof IStats;
const statData = returned[statKey]; const statData = returned[statKey];
@ -63,21 +67,19 @@ export const StatsManager = ({
}, },
{ promoted: [], table: [] } as IStructuredStats { promoted: [], table: [] } as IStructuredStats
); );
};
setData(structured); export const StatsManager = ({ className }: StatsManagerProps) => {
setError(null); const { VEGA_ENV } = useEnvironment();
} catch (e) { const { data, error, startPolling, stopPolling } =
setData(null); useQuery<NetworkStats>(STATS_QUERY);
setError(e as Error);
}
}
const interval = setInterval(getStats, 1000); useEffect(() => {
startPolling(1000);
return () => stopPolling();
});
return () => { const displayData = compileData(data);
clearInterval(interval);
};
}, [nodesEndpoint, statsEndpoint]);
const classes = classnames( const classes = classnames(
className, className,
@ -90,12 +92,13 @@ export const StatsManager = ({
data-testid="stats-environment" data-testid="stats-environment"
className="font-alpha uppercase text-h3 pb-16 col-span-full" className="font-alpha uppercase text-h3 pb-16 col-span-full"
> >
{(error && `/ ${error}`) || (data ? `/ ${envName}` : '/ Connecting...')} {(error && `/ ${error}`) ||
(data ? `/ ${VEGA_ENV}` : '/ Connecting...')}
</h3> </h3>
{data?.promoted ? ( {displayData?.promoted ? (
<PromotedStats> <PromotedStats>
{data.promoted.map((stat, i) => { {displayData.promoted.map((stat, i) => {
return ( return (
<PromotedStatsItem <PromotedStatsItem
title={stat.title} title={stat.title}
@ -111,8 +114,8 @@ export const StatsManager = ({
) : null} ) : null}
<Table> <Table>
{data?.table {displayData?.table
? data.table.map((stat, i) => { ? displayData.table.map((stat, i) => {
return ( return (
<TableRow <TableRow
title={stat.title} title={stat.title}

View File

@ -1,10 +1,10 @@
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers'; import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import type { Stats as IStats, StatFields as IStatFields } from './types'; import type { Stats, StatFields } from './types';
// Stats fields config. Keys will correspond to graphql queries when used, and values // Stats fields config. Keys will correspond to graphql queries when used, and values
// contain the associated data and methods we need to render. A single query // contain the associated data and methods we need to render. A single query
// can be rendered in multiple ways (see 'upTime'). // can be rendered in multiple ways (see 'upTime').
export const statsFields: { [key in keyof IStats]: IStatFields[] } = { export const statsFields: { [key in keyof Stats]: StatFields[] } = {
status: [ status: [
{ {
title: t('Status'), title: t('Status'),
@ -17,7 +17,7 @@ export const statsFields: { [key in keyof IStats]: IStatFields[] } = {
if (i === -1) { if (i === -1) {
return status; return status;
} else { } else {
return status.substr(i + 1); return status.substring(i + 1);
} }
}, },
goodThreshold: (status: string) => goodThreshold: (status: string) =>

View File

@ -1,22 +1,10 @@
export interface Stats { import type {
blockHeight: string; NetworkStats_nodeData,
totalNodes: string; NetworkStats_statistics,
validatingNodes: string; } from '../components/stats-manager/__generated__/NetworkStats';
inactiveNodes: string;
stakedTotal: string; export type Stats = Omit<NetworkStats_nodeData, '__typename'> &
backlogLength: string; Omit<NetworkStats_statistics, '__typename'>;
tradesPerSecond: string;
averageOrdersPerBlock: string;
ordersPerSecond: string;
txPerBlock: string;
blockDuration: string;
status: string;
vegaTime: string;
appVersion: string;
chainVersion: string;
uptime: string;
chainId: string;
}
// eslint-disable-next-line // eslint-disable-next-line
export type value = any; export type value = any;