From 3e5fea902e7d726ba5ab4d38ffaf5a3d45404bd7 Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 11:07:43 +0200 Subject: [PATCH 1/6] update --- backend/src/client/parentchain/contract.ts | 13 ++ backend/src/client/parentchain/index.ts | 10 + backend/src/controllers/account.controller.ts | 1 + backend/src/server.ts | 2 +- backend/src/services/block.service.ts | 13 +- .../src/components/info-cards/InfoCards.tsx | 175 +++++++++++------- frontend/src/types/info.d.ts | 11 +- frontend/src/types/loaderData.d.ts | 1 + 8 files changed, 155 insertions(+), 71 deletions(-) diff --git a/backend/src/client/parentchain/contract.ts b/backend/src/client/parentchain/contract.ts index 99eed41..bb548bd 100644 --- a/backend/src/client/parentchain/contract.ts +++ b/backend/src/client/parentchain/contract.ts @@ -69,6 +69,19 @@ export const abi = [ name: 'SubnetBlockFinalized', type: 'event', }, + { + inputs: [], + name: 'MODE', + outputs: [ + { + internalType: 'string', + name: '', + type: 'string', + }, + ], + stateMutability: 'view', + type: 'function', + }, { constant: true, inputs: [ diff --git a/backend/src/client/parentchain/index.ts b/backend/src/client/parentchain/index.ts index e3da7ad..c816975 100644 --- a/backend/src/client/parentchain/index.ts +++ b/backend/src/client/parentchain/index.ts @@ -58,6 +58,16 @@ export class ParentChainClient { } } + async mode(): Promise { + try { + const result = await this.smartContractInstance.methods.MODE().call(); + return result; + } catch (error) { + logger.error("Error while trying to fetch the last audited subnet's block in XDC mainnet", { message: error.message }); + throw new HttpException(500, error.message ? error.message : 'Error while trying to fetch the last audited subnet block in XDC parentchain'); + } + } + /** * * @param committedSubnetBlockHash WARNING: This method only check against the block has that has already been committed, otherwise always 0 diff --git a/backend/src/controllers/account.controller.ts b/backend/src/controllers/account.controller.ts index 0ead27c..e6d0ee0 100644 --- a/backend/src/controllers/account.controller.ts +++ b/backend/src/controllers/account.controller.ts @@ -27,6 +27,7 @@ export class RelayerController { health: { status: processingBacklog.isProcessing ? 'UP' : 'DOWN', }, + mode: processingBacklog.mode, }; res.status(200).json(resp); } catch (error) { diff --git a/backend/src/server.ts b/backend/src/server.ts index 5036c1d..bf66b89 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -9,7 +9,7 @@ const app = new App([new Route()]); const server = http.createServer(app.getServer()); const eventHandler = new EventsHandler(server); -server.listen(3000, () => { +server.listen(3001, () => { eventHandler.init(); logger.info(`=================================`); logger.info('🚀 Subnet Stats Service listening on the port 3000'); diff --git a/backend/src/services/block.service.ts b/backend/src/services/block.service.ts index b056daf..78c6ca8 100644 --- a/backend/src/services/block.service.ts +++ b/backend/src/services/block.service.ts @@ -135,7 +135,7 @@ export class BlockService { } // Returns the block num difference between what's mined in subnet and what's submitted to parent chain - public async getProcessingBacklog(): Promise<{ gap: number; isProcessing: boolean }> { + public async getProcessingBacklog(): Promise<{ gap: number; isProcessing: boolean; mode: string }> { const [lastSubnetCommittedBlock, smartContractProcessingInfo] = await Promise.all([ this.getLastSubnetCommittedBlock(), this.getSmartContractProcessingInfo(), @@ -143,6 +143,7 @@ export class BlockService { return { gap: lastSubnetCommittedBlock.number - smartContractProcessingInfo.processedUntil || -1, isProcessing: smartContractProcessingInfo.isProcessing, + mode: smartContractProcessingInfo.mode, }; } @@ -206,16 +207,22 @@ export class BlockService { }; } - private async getSmartContractProcessingInfo(): Promise<{ processedUntil: number; isProcessing: boolean }> { + private async getSmartContractProcessingInfo(): Promise<{ processedUntil: number; isProcessing: boolean; mode: string }> { const { smartContractHeight, smartContractCommittedHash } = await this.getAndSetLastSubmittedBlockInfo(); + const mode = await this.parentChainClient.mode(); const { timestamp } = await this.parentChainClient.getParentChainBlockBySubnetHash(smartContractCommittedHash); let isProcessing = true; const timeDiff = new Date().getTime() / 1000 - parseInt(timestamp.toString()); - if (timeDiff > 60) isProcessing = false; + if (mode == 'lite') { + if (timeDiff > 1000) isProcessing = false; + } else { + if (timeDiff > 60) isProcessing = false; + } return { processedUntil: smartContractHeight, isProcessing, + mode, }; } diff --git a/frontend/src/components/info-cards/InfoCards.tsx b/frontend/src/components/info-cards/InfoCards.tsx index bd2bfe4..451052c 100644 --- a/frontend/src/components/info-cards/InfoCards.tsx +++ b/frontend/src/components/info-cards/InfoCards.tsx @@ -1,18 +1,19 @@ -import axios from 'axios'; -import { useState } from 'react'; -import { useLoaderData } from 'react-router-dom'; +import axios from "axios"; +import { useState } from "react"; +import { useLoaderData } from "react-router-dom"; import { - BlocksInfoItem, MasterNode -} from '@/components/blocks-info/blocks-info-item/BlocksInfoItem'; -import BlocksInfo from '@/components/blocks-info/BlocksInfo'; -import Card from '@/components/card/Card'; -import InfoList from '@/components/info-list/InfoList'; -import { baseUrl } from '@/constants/urls'; -import { Info, InfoListHealth } from '@/types/info'; -import { HomeLoaderData } from '@/types/loaderData'; -import { getSortedRecentBlocks, uniqReplaceByName } from '@/utils/blockHelper'; -import { formatHash, formatMoney } from '@/utils/formatter'; + BlocksInfoItem, + MasterNode, +} from "@/components/blocks-info/blocks-info-item/BlocksInfoItem"; +import BlocksInfo from "@/components/blocks-info/BlocksInfo"; +import Card from "@/components/card/Card"; +import InfoList from "@/components/info-list/InfoList"; +import { baseUrl } from "@/constants/urls"; +import { Info, InfoListHealth } from "@/types/info"; +import { HomeLoaderData } from "@/types/loaderData"; +import { getSortedRecentBlocks, uniqReplaceByName } from "@/utils/blockHelper"; +import { formatHash, formatMoney } from "@/utils/formatter"; interface InfoCardsProps { nextFetchRecentBlocksIndex: number; @@ -30,38 +31,49 @@ export default function InfoCards(props: InfoCardsProps) { recentBlocks, setRecentBlocks, isLoadingRecentBlocks, - setIsLoadingRecentBlocks + setIsLoadingRecentBlocks, } = props; const loaderData = useLoaderData() as HomeLoaderData; const [veryFirstSubnetBlock] = useState(loaderData.blocks?.blocks[0].number); - const [isFetchingMoreRecentBlocks, setIsLoadingMoreRecentBlocks] = useState(false); - const [isReachApiEndOfRecentBlocks, setIsReachApiEndOfRecentBlocks] = useState(false); + const [isFetchingMoreRecentBlocks, setIsLoadingMoreRecentBlocks] = + useState(false); + const [isReachApiEndOfRecentBlocks, setIsReachApiEndOfRecentBlocks] = + useState(false); function getNetworkStatus(): InfoListHealth { - if (loaderData.network?.health.status === 'UP') { - return 'Normal'; + if (loaderData.network?.health.status === "UP") { + return "Normal"; } - return 'Abnormal'; + return "Abnormal"; } function getRelayerStatus(): InfoListHealth { - if (loaderData.relayer?.health.status === 'UP') { - return 'Normal'; + if (Number(loaderData.relayer?.account.balance) < 1) { + return "Low funds"; + } + if (loaderData.relayer?.health.status === "UP") { + return "Normal"; } - return 'Abnormal'; + return "Abnormal"; } - const mappedInfo: Info = getMappedInfo(loaderData, getNetworkStatus, getRelayerStatus); + const mappedInfo: Info = getMappedInfo( + loaderData, + getNetworkStatus, + getRelayerStatus + ); - const masterNodes = loaderData.masterNodes?.nodes?.map((v, i: number) => ({ - ...v, - type: 'master-node', - account: v.address, - number: i + 1 - })); + const masterNodes = loaderData.masterNodes?.nodes?.map( + (v, i: number) => ({ + ...v, + type: "master-node", + account: v.address, + number: i + 1, + }) + ); const fetchMoreRecentBlocks = async () => { if (!recentBlocks || !veryFirstSubnetBlock) { @@ -69,7 +81,9 @@ export default function InfoCards(props: InfoCardsProps) { } setIsLoadingMoreRecentBlocks(true); - const { data } = await axios.get(`${baseUrl}/information/blocks?blockNumIndex=${nextFetchRecentBlocksIndex}`); + const { data } = await axios.get( + `${baseUrl}/information/blocks?blockNumIndex=${nextFetchRecentBlocksIndex}` + ); const firstBlockNumber = data.blocks[0].number; @@ -81,7 +95,10 @@ export default function InfoCards(props: InfoCardsProps) { // concat data from api in the end of list since it would be the 'previous' data setRecentBlocks((recentBlocks: BlocksInfoItem[]) => { - const newRecentBlocks = uniqReplaceByName(recentBlocks, getSortedRecentBlocks(data.blocks)); + const newRecentBlocks = uniqReplaceByName( + recentBlocks, + getSortedRecentBlocks(data.blocks) + ); setIsLoadingMoreRecentBlocks(false); // Reach API limit @@ -95,31 +112,22 @@ export default function InfoCards(props: InfoCardsProps) { return ( <> -
- - +
+ + - - + + - - + +
-
- +
+ - - + +
); } -function getMappedInfo(loaderData: HomeLoaderData, getNetworkStatus: () => InfoListHealth, getRelayerStatus: () => InfoListHealth): Info { +function getMappedInfo( + loaderData: HomeLoaderData, + getNetworkStatus: () => InfoListHealth, + getRelayerStatus: () => InfoListHealth +): Info { const info: Info = {}; if (loaderData.network) { info.network = { health: getNetworkStatus(), data: [ - { name: 'Block Time', value: `${Math.floor(loaderData.network.subnet.block.averageBlockTime * 100) / 100}s` }, - { name: 'TX Throughput', value: `${Math.round(loaderData.network.subnet.block.txThroughput * 100) / 100} txs/s` }, - { name: 'Checkpointed to', value: loaderData.network.parentChain.name }, - ] + { + name: "Block Time", + value: `${ + Math.floor(loaderData.network.subnet.block.averageBlockTime * 100) / + 100 + }s`, + }, + { + name: "TX Throughput", + value: `${ + Math.round(loaderData.network.subnet.block.txThroughput * 100) / 100 + } txs/s`, + }, + { name: "Checkpointed to", value: loaderData.network.parentChain.name }, + ], }; } if (loaderData.relayer) { info.relayer = { health: getRelayerStatus(), data: [ - { name: 'Smart Contract', value: formatHash(loaderData.relayer.contractAddress) }, - { name: 'Backlog', value: `${loaderData.relayer.backlog} Subnet Headers` }, - { name: 'Remaining Balance', value: formatMoney(parseInt(loaderData.relayer.account.balance)) }, - ] + { + name: "Smart Contract", + value: `${formatHash(loaderData.relayer.contractAddress)}(mode : ${ + loaderData.relayer.mode + })`, + }, + { + name: "Backlog", + value: `${loaderData.relayer.backlog} Subnet Headers`, + }, + { + name: "Remaining Balance", + value: formatMoney(parseInt(loaderData.relayer.account.balance))+" XDC", + }, + ], }; } if (loaderData.masterNodes) { info.masterNodes = { data: [ - { name: 'Current committee size', value: loaderData.masterNodes?.summary?.committee }, - { name: 'Activity(active / inactive)', value: `${loaderData.masterNodes?.summary?.activeNodes} / ${loaderData.masterNodes.summary.committee - loaderData.masterNodes?.summary?.activeNodes}` }, - { name: 'Number of standby nodes', value: loaderData.masterNodes?.summary?.inActiveNodes }, + { + name: "Current committee size", + value: loaderData.masterNodes?.summary?.committee, + }, + { + name: "Activity(active / inactive)", + value: `${loaderData.masterNodes?.summary?.activeNodes} / ${ + loaderData.masterNodes.summary.committee - + loaderData.masterNodes?.summary?.activeNodes + }`, + }, + { + name: "Number of standby nodes", + value: loaderData.masterNodes?.summary?.inActiveNodes, + }, ], }; } return info; } - diff --git a/frontend/src/types/info.d.ts b/frontend/src/types/info.d.ts index 661c780..27e715c 100644 --- a/frontend/src/types/info.d.ts +++ b/frontend/src/types/info.d.ts @@ -12,6 +12,13 @@ export namespace InfoListInfo { } } -export type InfoListHealth = 'Normal' | 'Abnormal'; +export type InfoListHealth = "Normal" | "Abnormal" | "Low funds"; -export type InfoNames = 'masterNodes' | 'relayer' | 'network' | 'parentChain' | 'transaction' | 'subnetBlock' | 'subnet'; \ No newline at end of file +export type InfoNames = + | "masterNodes" + | "relayer" + | "network" + | "parentChain" + | "transaction" + | "subnetBlock" + | "subnet"; diff --git a/frontend/src/types/loaderData.d.ts b/frontend/src/types/loaderData.d.ts index 4883a22..b9576f9 100644 --- a/frontend/src/types/loaderData.d.ts +++ b/frontend/src/types/loaderData.d.ts @@ -91,6 +91,7 @@ export namespace HomeLoaderData { details: string; }; averageTXfee: number; + mode:string; } export interface Network { From d410b2361bd554bf3cd46c6b512f6f4d989d520e Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 11:10:09 +0200 Subject: [PATCH 2/6] update --- backend/src/server.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/server.ts b/backend/src/server.ts index bf66b89..5036c1d 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -9,7 +9,7 @@ const app = new App([new Route()]); const server = http.createServer(app.getServer()); const eventHandler = new EventsHandler(server); -server.listen(3001, () => { +server.listen(3000, () => { eventHandler.init(); logger.info(`=================================`); logger.info('🚀 Subnet Stats Service listening on the port 3000'); From eeb1b6ae07c0226bd769d549b7df6306ff596fd5 Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 11:23:04 +0200 Subject: [PATCH 3/6] update --- backend/src/services/block.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/block.service.ts b/backend/src/services/block.service.ts index 78c6ca8..3f59f9b 100644 --- a/backend/src/services/block.service.ts +++ b/backend/src/services/block.service.ts @@ -216,7 +216,7 @@ export class BlockService { if (mode == 'lite') { if (timeDiff > 1000) isProcessing = false; } else { - if (timeDiff > 60) isProcessing = false; + if (timeDiff > 120) isProcessing = false; } return { From 66eb5920220690815f8db28b59b677880a68292f Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 14:18:04 +0200 Subject: [PATCH 4/6] update --- backend/src/services/block.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/block.service.ts b/backend/src/services/block.service.ts index 3f59f9b..73d790c 100644 --- a/backend/src/services/block.service.ts +++ b/backend/src/services/block.service.ts @@ -215,7 +215,7 @@ export class BlockService { const timeDiff = new Date().getTime() / 1000 - parseInt(timestamp.toString()); if (mode == 'lite') { if (timeDiff > 1000) isProcessing = false; - } else { + } else if (mode == 'full') { if (timeDiff > 120) isProcessing = false; } From abaa70f630da6c8726fe66ffb9fbe98d5b8e9088 Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 14:19:37 +0200 Subject: [PATCH 5/6] upfste --- backend/src/client/parentchain/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/client/parentchain/index.ts b/backend/src/client/parentchain/index.ts index c816975..91f1c78 100644 --- a/backend/src/client/parentchain/index.ts +++ b/backend/src/client/parentchain/index.ts @@ -63,8 +63,8 @@ export class ParentChainClient { const result = await this.smartContractInstance.methods.MODE().call(); return result; } catch (error) { - logger.error("Error while trying to fetch the last audited subnet's block in XDC mainnet", { message: error.message }); - throw new HttpException(500, error.message ? error.message : 'Error while trying to fetch the last audited subnet block in XDC parentchain'); + logger.error("Error while trying to fetch the mode in XDC mainnet", { message: error.message }); + throw new HttpException(500, error.message ? error.message : 'Error while trying to fetch the mode in XDC parentchain'); } } From 7184c89f558f4c70a3786eca55dedc275af94344 Mon Sep 17 00:00:00 2001 From: Galaxy <429224280@qq.com> Date: Tue, 12 Sep 2023 19:55:57 +0200 Subject: [PATCH 6/6] update --- backend/src/services/block.service.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/backend/src/services/block.service.ts b/backend/src/services/block.service.ts index 73d790c..5b7e6b6 100644 --- a/backend/src/services/block.service.ts +++ b/backend/src/services/block.service.ts @@ -211,13 +211,10 @@ export class BlockService { const { smartContractHeight, smartContractCommittedHash } = await this.getAndSetLastSubmittedBlockInfo(); const mode = await this.parentChainClient.mode(); const { timestamp } = await this.parentChainClient.getParentChainBlockBySubnetHash(smartContractCommittedHash); - let isProcessing = true; + const timeDiff = new Date().getTime() / 1000 - parseInt(timestamp.toString()); - if (mode == 'lite') { - if (timeDiff > 1000) isProcessing = false; - } else if (mode == 'full') { - if (timeDiff > 120) isProcessing = false; - } + + const isProcessing = (mode == 'full' && timeDiff < 120) || (mode == 'lite' && timeDiff < 1000); return { processedUntil: smartContractHeight,