diff --git a/packages/backend/src/Aggregator.ts b/packages/backend/src/Aggregator.ts index f730ea3..45c69ac 100644 --- a/packages/backend/src/Aggregator.ts +++ b/packages/backend/src/Aggregator.ts @@ -2,7 +2,7 @@ import Chain from './Chain'; import Node from './Node'; import Feed from './Feed'; import FeedSet from './FeedSet'; -import { Types, FeedMessage, timestamp } from '@dotstats/common'; +import { Types, FeedMessage, Maybe, timestamp } from '@dotstats/common'; export default class Aggregator { private readonly chains = new Map(); @@ -48,6 +48,10 @@ export default class Aggregator { }); } + public getExistingChain(label: Types.ChainLabel) : Maybe { + return this.chains.get(label); + } + private getChain(label: Types.ChainLabel): Chain { const chain = this.chains.get(label); diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts index 7f2826e..ea61a4b 100644 --- a/packages/backend/src/index.ts +++ b/packages/backend/src/index.ts @@ -1,7 +1,10 @@ +import * as http from 'http'; +import * as url from 'url'; import * as WebSocket from 'ws'; import Node from './Node'; import Feed from './Feed'; import Aggregator from './Aggregator'; +import {Types} from '@dotstats/common'; const WS_PORT_TELEMETRY_SERVER = Number(process.env.TELEMETRY_SERVER || 1024); const WS_PORT_FEED_SERVER = Number(process.env.FEED_SERVER || 8080); @@ -47,3 +50,23 @@ logClients(); telemetryFeed.on('connection', (socket: WebSocket) => { aggregator.addFeed(new Feed(socket)); }); + +http.createServer((request, response) => { + const incoming_url = request.url || ""; + const parsed_url = url.parse(incoming_url, true); + const path = decodeURI(parsed_url.path || ""); + if (path.startsWith("/network_state/")) { + const [chainLabel, strNodeId] = path.split('/').slice(2); + const chain = aggregator.getExistingChain(chainLabel as Types.ChainLabel); + if (chain) { + const nodeList = Array.from(chain.nodeList()); + const nodeId = Number(strNodeId); + const node = nodeList.filter((node) => node.id == nodeId)[0]; + if (node) { + response.writeHead(200, {"Content-Type": "application/json"}); + response.write(node.networkState); + } + } + } + response.end(); +}).listen(8081); diff --git a/packages/frontend/src/App.tsx b/packages/frontend/src/App.tsx index 2160e01..c75fd11 100644 --- a/packages/frontend/src/App.tsx +++ b/packages/frontend/src/App.tsx @@ -35,7 +35,8 @@ export default class App extends React.Component<{}, State> { finalized: false, finalizedhash: false, blockpropagation: true, - blocklasttime: false + blocklasttime: false, + networkstate: false, }, (settings) => this.setState({ settings }) ); diff --git a/packages/frontend/src/components/List/Row.tsx b/packages/frontend/src/components/List/Row.tsx index de8b10c..d724fea 100644 --- a/packages/frontend/src/components/List/Row.tsx +++ b/packages/frontend/src/components/List/Row.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import Identicon from 'polkadot-identicon'; import { Types, Maybe, timestamp } from '@dotstats/common'; -import { formatNumber, milliOrSecond, secondsWithPrecision } from '../../utils'; +import { formatNumber, getHashData, milliOrSecond, secondsWithPrecision } from '../../utils'; import { State as AppState, Node } from '../../state'; import { PersistentSet } from '../../persist'; import { Truncate } from './'; @@ -281,6 +281,17 @@ export class Row extends React.Component { setting: 'blocklasttime', render: ({ blockTimestamp }) => }, + { + label: 'NetworkState', + icon: networkIdIcon, + width: 100, + setting: 'networkstate', + render: ({ id }) => { + const chainLabel = getHashData().chain; + const uri = encodeURI(`/network_state/${chainLabel}/${id}/`); + return React.createElement('a', {href: uri, target: "_blank"}, "Network state"); + }, + }, ]; public static Header = (props: HeaderProps) => { diff --git a/packages/frontend/src/state.ts b/packages/frontend/src/state.ts index f51f9f4..042532c 100644 --- a/packages/frontend/src/state.ts +++ b/packages/frontend/src/state.ts @@ -174,6 +174,7 @@ export namespace State { blocktime: boolean; blockpropagation: boolean; blocklasttime: boolean; + networkstate: boolean; } }