diff --git a/src/App.tsx b/src/App.tsx index bd9da0d3..17e023cd 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -17,12 +17,10 @@ import { QueryApolloProvider, SQTokenProvider, } from './containers'; -import RouterComponent, { ScannerRouterComponent } from './router'; +import RouterComponent from './router'; import './App.css'; -const isScanner = window.location.host.includes('scanner') || import.meta.env.VITE_USE_SCANNER; - // TODO: Remove SQTProvider const Providers: React.FC = ({ children }) => { return ( @@ -33,7 +31,7 @@ const Providers: React.FC = ({ children }) => { - {children} + {children} @@ -79,32 +77,17 @@ const RenderRouter: React.FC = () => { return ( - <> - {isScanner ? ( -
- - -
-
- ) : ( - '' - )} - {!isScanner ? ( -
-
-
-
+
+
+
+
-
- - - -
-
- ) : ( - '' - )} - +
+ + + +
+
); }; diff --git a/src/components/LineCharts/index.tsx b/src/components/LineCharts/index.tsx index e681aeb2..c59e33a4 100644 --- a/src/components/LineCharts/index.tsx +++ b/src/components/LineCharts/index.tsx @@ -123,6 +123,7 @@ const LineCharts: FC = ({ )} { - const { - title = 'Node Operator Rewards', - dataDimensionsName = ['Stake Rewards', 'Query Rewards'], - chartsStyle, - skeletonHeight, - } = props; - const { currentEra } = useEra(); - const [filter, setFilter] = useState({ date: 'lm' }); - const [renderRewards, setRenderRewards] = useState([[]]); - const [rawRewardsData, setRawRewardsData] = useState<{ allocation: number[]; query: number[]; total: number[] }>({ - allocation: [], - query: [], - total: [], - }); - - const rewardsLineXScales = useMemo(() => { - const getXScales = (period: number, filterVal: FilterType) => { - const getDefaultScales = xAxisScalesFunc(period); - - const result = getDefaultScales[filterVal.date](); - return result.slice(0, result.length - 1); - }; - const slicedResult = getXScales(currentEra.data?.period || 0, filter); - return { - val: { - renderData: slicedResult.map((i) => i.format('MMM D')), - rawData: slicedResult, - }, - getXScales, - }; - }, [filter.date, currentEra]); - - const [fetchRewards, rewardsData] = useLazyQuery<{ - eraDeploymentRewards: { - groupedAggregates: { keys: string[]; sum: { allocationRewards: string; totalRewards: string } }[]; - }; - }>(gql` - query fetchRewards($eraIds: [Int!]!) { - eraDeploymentRewards(filter: { eraIdx: { in: $eraIds } }) { - groupedAggregates(groupBy: ERA_IDX) { - keys - sum { - allocationRewards - totalRewards - } - } - } - } - `); - - const fetchRewardsByEra = async (filterVal: FilterType | undefined = filter) => { - if (!currentEra.data) return; - if (!filterVal) return; - const { getIncludesEras, fillData } = getSplitDataByEra(currentEra.data); - const { includesEras, includesErasHex } = { - lm: () => getIncludesEras(dayjs().subtract(31, 'day')), - l3m: () => getIncludesEras(dayjs().subtract(90, 'day')), - ly: () => getIncludesEras(dayjs().subtract(365, 'day')), - }[filterVal.date](); - const apis = fetchRewards; - const vars = { - eraIds: includesEras, - indexerId: props.account || '', - }; - const res = await apis({ - variables: vars, - fetchPolicy: 'no-cache', - }); - - const maxPaddingLength = rewardsLineXScales.getXScales(currentEra.data.period, filterVal).length; - - // // rewards don't want to show lastest era data - const removedLastEras = includesErasHex.slice(1, includesErasHex.length); - const curry = ['0']>(data: T) => - fillData(data, removedLastEras, maxPaddingLength); - const allocationRewards = curry( - res?.data?.eraDeploymentRewards?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - - sum: { - amount: i.sum.allocationRewards, - }, - }; - }) || [], - ); - - const queryRewards = curry( - res?.data?.eraDeploymentRewards?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - - sum: { - amount: BigNumberJs(i.sum.totalRewards).minus(i.sum.allocationRewards).toString(), - }, - }; - }) || [], - ); - - const totalRewards = curry( - res?.data?.eraDeploymentRewards?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - sum: { - amount: i.sum.totalRewards, - }, - }; - }) || [], - ); - setRawRewardsData({ - allocation: allocationRewards, - query: queryRewards, - total: totalRewards, - }); - - setRenderRewards([allocationRewards, queryRewards]); - }; - - useEffect(() => { - fetchRewardsByEra(); - }, [currentEra.data?.index, props.account]); - - return renderAsync( - { - ...rewardsData, - loading: rewardsData.previousData ? false : rewardsData.loading, - data: rewardsData.data || rewardsData.previousData, - }, - { - loading: () => ( - - ), - error: (e) => {parseError(e)}, - data: () => { - return ( - { - setFilter(val); - fetchRewardsByEra(val); - }} - style={chartsStyle} - xAxisScales={rewardsLineXScales.val} - title={title} - dataDimensionsName={dataDimensionsName} - chartData={renderRewards} - onTriggerTooltip={(index, curDate) => { - return `
- ${curDate.format('MMM D, YYYY')} -
- Total - ${formatNumber(rawRewardsData.total[index])} ${TOKEN} -
-
- ${dataDimensionsName[0]} - ${formatNumber(rawRewardsData.allocation[index])} ${TOKEN} (${toPercentage( - rawRewardsData.allocation[index], - rawRewardsData.total[index], - )}) -
-
- ${dataDimensionsName[1]} - ${formatNumber(rawRewardsData.query[index])} ${TOKEN} (${toPercentage( - rawRewardsData.query[index], - rawRewardsData.total[index], - )}) -
-
`; - }} - >
- ); - }, - }, - ); -}; diff --git a/src/pages/scanner/dashboard/index.module.less b/src/pages/scanner/dashboard/index.module.less deleted file mode 100644 index a9e65c36..00000000 --- a/src/pages/scanner/dashboard/index.module.less +++ /dev/null @@ -1,18 +0,0 @@ -.dashboard { - padding: 24px; - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - gap: 24px; - - &Inner { - padding: 24px; - border: 1px solid var(--dark-mode-border); - border-radius: 8px; - height: 100%; - width: 100%; - flex: 1; - background: var(--dark-mode-card); - } -} \ No newline at end of file diff --git a/src/pages/scanner/dashboard/index.tsx b/src/pages/scanner/dashboard/index.tsx deleted file mode 100644 index af2d09df..00000000 --- a/src/pages/scanner/dashboard/index.tsx +++ /dev/null @@ -1,356 +0,0 @@ -import React, { FC, useMemo } from 'react'; -import { gql, useQuery } from '@apollo/client'; -import { DeploymentMeta } from '@components'; -import { useEra } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { Typography } from '@subql/components'; -import { useAsyncMemo } from '@subql/react-hooks'; -import { TOKEN } from '@utils'; -import { Button, Table } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import dayjs from 'dayjs'; - -import { formatNumber, formatSQT } from '../../../utils/numberFormatters'; -import { OperatorRewardsLineChart } from './components/operatorRewardsChart/OperatorRewardsLineChart'; -import styles from './index.module.less'; - -interface IProps {} - -const ScannerDashboard: FC = (props) => { - const { currentEra } = useEra(); - const { getStatisticQueries } = useConsumerHostServices({ - autoLogin: false, - }); - const top5Deployments = useQuery<{ - eraDeploymentRewards: { - nodes: { deploymentId: string; totalRewards: string }[]; - }; - }>( - gql` - query top5Deployments($currentIdx: Int!) { - eraDeploymentRewards(orderBy: TOTAL_REWARDS_DESC, filter: { eraIdx: { equalTo: $currentIdx } }, first: 5) { - nodes { - deploymentId - totalRewards - } - } - } - `, - { - variables: { - currentIdx: (currentEra.data?.index || 0) - 1, - }, - }, - ); - - const top5DeploymentsInfomations = useQuery<{ - deployments: { - nodes: { - id: string; - metadata: string; - project: { - metadata: string; - }; - indexers: { - totalCount: number; - }; - }[]; - }; - indexerAllocationSummaries: { - groupedAggregates: { keys: string[]; sum: { totalAmount: string } }[]; - }; - deploymentBoosterSummaries: { - groupedAggregates: { keys: string[]; sum: { totalAmount: string } }[]; - }; - eraDeploymentRewards: { - groupedAggregates: { keys: string[]; sum: { allocationRewards: string; totalRewards: string } }[]; - }; - }>( - gql` - query top5DeploymentsInfomations($deploymentIds: [String!], $currentIdx: Int!) { - deployments(filter: { id: { in: $deploymentIds } }) { - nodes { - id - metadata - project { - metadata - } - indexers(filter: { indexer: { active: { equalTo: true } }, status: { notEqualTo: TERMINATED } }) { - totalCount - } - } - } - - indexerAllocationSummaries(filter: { deploymentId: { in: $deploymentIds } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - totalAmount - } - } - } - - deploymentBoosterSummaries(filter: { deploymentId: { in: $deploymentIds } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - totalAmount - } - } - } - - eraDeploymentRewards(filter: { deploymentId: { in: $deploymentIds }, eraIdx: { equalTo: $currentIdx } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - allocationRewards - totalRewards - } - } - } - } - `, - { - variables: { - deploymentIds: top5Deployments.data?.eraDeploymentRewards.nodes.map((node: any) => node.deploymentId) || [], - currentIdx: (currentEra.data?.index || 0) - 1, - }, - }, - ); - - const queries = useAsyncMemo(async () => { - if (!currentEra.data) return []; - const deployments = top5Deployments.data?.eraDeploymentRewards.nodes.map((i) => i.deploymentId); - if (!deployments || !deployments?.length) return []; - try { - const res = await getStatisticQueries({ - deployment: deployments, - start_date: dayjs(currentEra.data.eras?.at(1)?.startTime).format('YYYY-MM-DD'), - end_date: dayjs(currentEra.data.eras?.at(1)?.endTime).format('YYYY-MM-DD'), - }); - - return res.data.list; - } catch (e) { - return []; - } - }, [top5Deployments.data, currentEra.data?.eras]); - - const renderData = useMemo(() => { - if (top5Deployments.loading || top5DeploymentsInfomations.loading) return []; - - return top5Deployments.data?.eraDeploymentRewards.nodes.map((node, index) => { - const eraDeploymentRewardsItem = top5DeploymentsInfomations.data?.eraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - ); - const allocationRewards = eraDeploymentRewardsItem?.sum.allocationRewards || '0'; - const totalCount = top5DeploymentsInfomations.data?.deployments.nodes.find((i) => i.id === node.deploymentId) - ?.indexers.totalCount; - - const totalAllocation = - top5DeploymentsInfomations.data?.indexerAllocationSummaries.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - )?.sum.totalAmount || '0'; - const totalQueryRewards = BigNumberJs(eraDeploymentRewardsItem?.sum.totalRewards || '0') - .minus(allocationRewards) - .toFixed(); - const deploymentInfo = top5DeploymentsInfomations.data?.deployments.nodes.find((i) => i.id === node.deploymentId); - - const deploymentQueryCount = queries.data?.find((i) => i.deployment === node.deploymentId); - - return { - deploymentId: node.deploymentId, - projectMetadata: deploymentInfo?.project.metadata, - operatorCount: totalCount, - allocationAmount: formatNumber(formatSQT(totalAllocation)), - boosterAmount: formatNumber( - formatSQT( - top5DeploymentsInfomations.data?.deploymentBoosterSummaries.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - )?.sum.totalAmount || '0', - ), - ), - allocationRewards: formatNumber(formatSQT(allocationRewards)), - averageAllocationRewards: formatNumber( - formatSQT( - BigNumberJs(allocationRewards) - .div(totalCount || 1) - .toFixed(), - ), - ), - allocationApy: BigNumberJs(allocationRewards) - .div(totalAllocation === '0' ? '1' : totalAllocation) - .multipliedBy(52) - .multipliedBy(100) - .toFixed(2), - queryRewards: formatNumber(formatSQT(totalQueryRewards)), - averageQueryRewards: formatNumber( - formatSQT( - BigNumberJs(totalQueryRewards) - .div(totalCount || 1) - .toFixed(), - ), - ), - queries: formatNumber(deploymentQueryCount?.queries || 0, 0), - averageQueries: formatNumber( - BigNumberJs(deploymentQueryCount?.queries || 0) - .div(totalCount || 1) - .toFixed(), - 0, - ), - totalRewards: formatNumber(formatSQT(eraDeploymentRewardsItem?.sum.totalRewards || '0')), - averageRewards: formatNumber( - formatSQT( - BigNumberJs(eraDeploymentRewardsItem?.sum.totalRewards || '0') - .div(totalCount || 1) - .toFixed(), - ), - ), - }; - }); - }, [top5Deployments, top5DeploymentsInfomations, queries]); - - return ( -
- - Dashboard - - -
-
- - Top 5 Project Rewards - - - -
- - record.deploymentId} - className={'darkTable'} - loading={top5Deployments.loading || top5DeploymentsInfomations.loading} - columns={[ - { - title: 'Project', - dataIndex: 'name', - key: 'name', - render: (_, record) => { - return ; - }, - }, - { - title: 'Node Operators', - dataIndex: 'operatorCount', - key: 'operatorCount', - }, - { - title: 'Stake', - dataIndex: 'allocationAmount', - key: 'allocationAmount', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Boost', - dataIndex: 'boosterAmount', - key: 'boosterAmount', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Total Stake Rewards', - dataIndex: 'allocationRewards', - key: 'allocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Average Stake Rewards', - dataIndex: 'averageAllocationRewards', - key: 'averageAllocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Stake Apy', - dataIndex: 'allocationApy', - key: 'allocationApy', - render: (text: string) => {text} %, - }, - { - title: 'Total Queries', - dataIndex: 'queries', - key: 'queries', - render: (text: string) => {text}, - }, - { - title: 'Average Queries', - dataIndex: 'averageQueries', - key: 'averageQueries', - render: (text: string) => {text}, - }, - { - title: 'Total Query Rewards', - dataIndex: 'queryRewards', - key: 'queryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Average Query Rewards', - dataIndex: 'averageQueryRewards', - key: 'averageQueryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Total Rewards', - dataIndex: 'totalRewards', - key: 'totalRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Average Rewards', - dataIndex: 'averageRewards', - key: 'averageRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - ]} - dataSource={renderData} - pagination={false} - scroll={{ x: 'max-content' }} - >
-
-
- ); -}; -export default ScannerDashboard; diff --git a/src/pages/scanner/nodeOperatorDetail/index.module.less b/src/pages/scanner/nodeOperatorDetail/index.module.less deleted file mode 100644 index a9e65c36..00000000 --- a/src/pages/scanner/nodeOperatorDetail/index.module.less +++ /dev/null @@ -1,18 +0,0 @@ -.dashboard { - padding: 24px; - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - gap: 24px; - - &Inner { - padding: 24px; - border: 1px solid var(--dark-mode-border); - border-radius: 8px; - height: 100%; - width: 100%; - flex: 1; - background: var(--dark-mode-card); - } -} \ No newline at end of file diff --git a/src/pages/scanner/nodeOperatorDetail/index.tsx b/src/pages/scanner/nodeOperatorDetail/index.tsx deleted file mode 100644 index b3c36bbb..00000000 --- a/src/pages/scanner/nodeOperatorDetail/index.tsx +++ /dev/null @@ -1,323 +0,0 @@ -import React, { FC, useCallback } from 'react'; -import { useNavigate, useParams } from 'react-router'; -import { gql, useQuery } from '@apollo/client'; -import { DeploymentInfo } from '@components'; -import { IndexerName } from '@components/IndexerDetails/IndexerName'; -import { useEra, useSortedIndexerDeployments } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { Typography } from '@subql/components'; -import { useAsyncMemo } from '@subql/react-hooks'; -import { TOKEN } from '@utils'; -import { Breadcrumb, Button, Table } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import clsx from 'clsx'; -import dayjs from 'dayjs'; - -import { formatNumber, formatSQT } from '../../../utils/numberFormatters'; -import { RewardsByType } from '../projectDetail/components/rewardsByType/rewardsByType'; -import styles from './index.module.less'; - -interface IProps {} - -const ScannerDashboard: FC = (props) => { - const { currentEra } = useEra(); - const { id } = useParams(); - const navigate = useNavigate(); - const { getUserQueriesAggregation, getStatisticQueries } = useConsumerHostServices({ - autoLogin: false, - }); - - const indexerRewardsInfos = useQuery<{ - eraIndexerApies: { - nodes: { - indexerId: string; - indexerApy: string; - }[]; - }; - indexerEraDeploymentRewards: { - groupedAggregates: { - sum: { - allocationRewards: string; - queryRewards: string; - totalRewards: string; - }; - keys: string[]; - }[]; - }; - }>( - gql` - query getIndexerRewardsInfos($indexers: [String!], $era: Int!) { - eraIndexerApies(filter: { eraIdx: { equalTo: $era }, indexerId: { in: $indexers } }) { - nodes { - indexerId - indexerApy - } - } - - indexerEraDeploymentRewards(filter: { indexerId: { in: $indexers } }) { - groupedAggregates(groupBy: INDEXER_ID) { - sum { - allocationRewards - queryRewards - totalRewards - } - keys - } - } - } - `, - { - variables: { - era: (currentEra.data?.index || 0) - 1, - indexers: [id], - }, - }, - ); - - const indexerDeployments = useSortedIndexerDeployments(id || ''); - - const queriesOfIndexers = useAsyncMemo(async () => { - if (!id || !currentEra.data?.index) { - return { - info: { total: '0' }, - }; - } - - const selectEraInfo = currentEra.data?.eras?.at(1); - - const startDate = dayjs(selectEraInfo?.startTime || '0').format('YYYY-MM-DD'); - - const endDate = selectEraInfo?.endTime ? dayjs(selectEraInfo?.endTime || '0').format('YYYY-MM-DD') : undefined; - - const queries = await getUserQueriesAggregation({ - user_list: [id.toLowerCase()], - start_date: startDate, - end_date: endDate, - }); - - return queries?.data?.[0] || { info: { total: '0' } }; - }, [currentEra.data?.index, id]); - - const queriesOfDeployments = useAsyncMemo(async () => { - if (!id || !currentEra.data?.index || !indexerDeployments.data) { - return []; - } - - const selectEraInfo = currentEra.data?.eras?.at(1); - - const startDate = dayjs(selectEraInfo?.startTime || '0').format('YYYY-MM-DD'); - - const endDate = selectEraInfo?.endTime ? dayjs(selectEraInfo?.endTime || '0').format('YYYY-MM-DD') : undefined; - - const queries = await getStatisticQueries({ - deployment: indexerDeployments.data.map((item) => item.deploymentId || ''), - indexer: [id.toLowerCase()], - start_date: startDate, - end_date: endDate, - }); - - return queries?.data?.list?.[0].list || []; - }, [currentEra.data?.index, indexerDeployments.data, id]); - - const getDeploymentQueries = useCallback( - (deployment: string) => { - if (Array.isArray(queriesOfDeployments.data)) { - return queriesOfDeployments.data?.find((i) => i.deployment === deployment)?.queries || 0; - } - - return 0; - }, - [queriesOfDeployments.data], - ); - - return ( -
- - Node Operators - - ), - onClick: () => { - navigate(`/node-operators`); - }, - }, - { - key: 'current', - title: ( - - {id} - - ), - }, - ]} - > - -
-
- - -
-
- - Project Rewards - - - - {formatNumber( - formatSQT( - indexerRewardsInfos.data?.indexerEraDeploymentRewards?.groupedAggregates?.[0]?.sum?.totalRewards || - '0', - ), - )}{' '} - {TOKEN} - -
- -
- - Projects - - - {indexerDeployments.data?.length || 0} -
- -
- - Stake Rewards - - - - {formatNumber( - formatSQT( - indexerRewardsInfos.data?.indexerEraDeploymentRewards?.groupedAggregates?.[0]?.sum - ?.allocationRewards || '0', - ), - )}{' '} - {TOKEN} - -
- -
- - Query Rewards - - - - {formatNumber( - formatSQT( - indexerRewardsInfos.data?.indexerEraDeploymentRewards?.groupedAggregates?.[0]?.sum?.queryRewards || - '0', - ), - )}{' '} - {TOKEN} - -
- -
- - Queries - - - - {BigNumberJs(queriesOfIndexers.data?.info.total || '0') - .div(10 ** 15) - .toFixed(0)} - -
-
-
-
- -
-
- -
-
- - Projects ({indexerDeployments.data?.length || 0}) - -
- - record.deploymentId || index || '0'} - className={'darkTable'} - loading={indexerDeployments.loading} - columns={[ - { - title: 'ProjectS', - dataIndex: 'name', - key: 'name', - render: (_, record) => { - return ( - - ); - }, - }, - { - title: 'Stake', - dataIndex: 'allocatedAmount', - key: 'allocatedAmount', - render: (text: string) => ( - - {text ? formatNumber(formatSQT(text)) : 0} {TOKEN} - - ), - }, - { - title: 'Last Era Stake Rewards', - dataIndex: 'lastEraAllocatedRewards', - key: 'lastEraAllocatedRewards', - render: (text: string) => ( - - {text ? formatNumber(formatSQT(text)) : 0} {TOKEN} - - ), - }, - { - title: 'Last Era Query Rewards', - dataIndex: 'lastEraQueryRewards', - key: 'lastEraQueryRewards', - render: (text: string) => ( - - {text ? formatNumber(formatSQT(text)) : 0} {TOKEN} - - ), - }, - { - title: 'Last Era Queries', - dataIndex: 'deploymentId', - key: 'deploymentId', - render: (deploymentId: string) => {getDeploymentQueries(deploymentId)}, - }, - { - title: 'Total Rewards', - dataIndex: 'totalRewards', - key: 'totalRewards', - render: (text: string) => ( - - {text ? formatNumber(formatSQT(text)) : 0} {TOKEN} - - ), - }, - ]} - dataSource={indexerDeployments.data || []} - pagination={false} - >
-
-
- ); -}; -export default ScannerDashboard; diff --git a/src/pages/scanner/nodeOperators/index.module.less b/src/pages/scanner/nodeOperators/index.module.less deleted file mode 100644 index a9e65c36..00000000 --- a/src/pages/scanner/nodeOperators/index.module.less +++ /dev/null @@ -1,18 +0,0 @@ -.dashboard { - padding: 24px; - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - gap: 24px; - - &Inner { - padding: 24px; - border: 1px solid var(--dark-mode-border); - border-radius: 8px; - height: 100%; - width: 100%; - flex: 1; - background: var(--dark-mode-card); - } -} \ No newline at end of file diff --git a/src/pages/scanner/nodeOperators/index.tsx b/src/pages/scanner/nodeOperators/index.tsx deleted file mode 100644 index 1f966730..00000000 --- a/src/pages/scanner/nodeOperators/index.tsx +++ /dev/null @@ -1,331 +0,0 @@ -import React, { FC, useEffect, useMemo, useState } from 'react'; -import { IoSearch } from 'react-icons/io5'; -import { useNavigate } from 'react-router'; -import { gql, useQuery } from '@apollo/client'; -import { DeploymentMeta } from '@components'; -import { IndexerName } from '@components/IndexerDetails/IndexerName'; -import { useAsyncMemo, useEra } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { CurrentEraValue, parseRawEraValue } from '@hooks/useEraValue'; -import { Typography } from '@subql/components'; -import { TOKEN } from '@utils'; -import { usePrevious } from 'ahooks'; -import { Button, Input, Select, Table } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import dayjs from 'dayjs'; -import { debounce } from 'lodash-es'; - -import { formatNumber, formatSQT } from '../../../utils/numberFormatters'; -import styles from './index.module.less'; - -interface IProps {} - -const ScannerDashboard: FC = (props) => { - const { currentEra } = useEra(); - const navigate = useNavigate(); - const { getUserQueriesAggregation } = useConsumerHostServices({ - autoLogin: false, - }); - const [selectEra, setSelectEra] = useState((currentEra.data?.index || 1) - 1 || 0); - const [searchDeployment, setSearchDeployment] = useState(''); - const debounceSearch = useMemo(() => debounce(setSearchDeployment, 500), [setSearchDeployment]); - const [pageInfo, setPageInfo] = useState({ - pageSize: 30, - currentPage: 1, - }); - - const blockHeightOfQuery = useMemo(() => { - if (!currentEra.data?.index) return '99999999999999999'; - - if (selectEra === currentEra.data.index - 1 || selectEra === currentEra.data.index) { - return '99999999999999999'; - } - - return currentEra.data.eras?.find((i) => parseInt(i.id, 16) === selectEra)?.createdBlock || '99999999999999999'; - }, [selectEra, currentEra.data?.index]); - - const allIndexers = useQuery<{ - indexers: { - nodes: { selfStake: CurrentEraValue; totalStake: CurrentEraValue; id: string }[]; - totalCount: number; - }; - }>( - gql` - query getAllIndexers($first: Int! = 30, $offset: Int! = 0, $indexerId: String = "", $blockHeight: String!) { - indexers( - blockHeight: $blockHeight - first: $first - offset: $offset - filter: { id: { includesInsensitive: $indexerId }, active: { equalTo: true } } - ) { - nodes { - selfStake - totalStake - id - } - totalCount - } - } - `, - { - variables: { - first: pageInfo.pageSize, - offset: (pageInfo.currentPage - 1) * pageInfo.pageSize, - indexerId: searchDeployment, - blockHeight: blockHeightOfQuery.toString(), - }, - }, - ); - - const indexerRewardsInfos = useQuery<{ - eraIndexerApies: { - nodes: { - indexerId: string; - indexerApy: string; - }[]; - }; - indexerEraDeploymentRewards: { - groupedAggregates: { - sum: { - allocationRewards: string; - queryRewards: string; - totalRewards: string; - }; - keys: string[]; - }[]; - }; - }>( - gql` - query getIndexerRewardsInfos($indexers: [String!], $era: Int!) { - eraIndexerApies(filter: { eraIdx: { equalTo: $era }, indexerId: { in: $indexers } }) { - nodes { - indexerId - indexerApy - } - } - - indexerEraDeploymentRewards(filter: { eraIdx: { equalTo: $era }, indexerId: { in: $indexers } }) { - groupedAggregates(groupBy: INDEXER_ID) { - sum { - allocationRewards - queryRewards - totalRewards - } - keys - } - } - } - `, - { - variables: { - era: selectEra, - indexers: allIndexers.data?.indexers.nodes.map((node) => node.id) || [], - }, - }, - ); - - const queriesOfAllIndexers = useAsyncMemo(async () => { - if (!allIndexers.data?.indexers.nodes.length || !currentEra.data?.index) { - return []; - } - - const selectEraInfo = currentEra.data?.eras?.find((i) => parseInt(i.id, 16) === selectEra); - - const startDate = dayjs(selectEraInfo?.startTime || '0').format('YYYY-MM-DD'); - - const endDate = selectEraInfo?.endTime ? dayjs(selectEraInfo?.endTime || '0').format('YYYY-MM-DD') : undefined; - - const queries = await getUserQueriesAggregation({ - user_list: allIndexers.data?.indexers.nodes.map((node) => node.id.toLowerCase()) || [], - start_date: startDate, - end_date: endDate, - }); - - return queries.data; - }, [currentEra.data?.index, allIndexers.data, selectEra]); - - const renderData = useMemo(() => { - if (!allIndexers.data?.indexers.nodes.length || !indexerRewardsInfos.data) { - return []; - } - - const indexerRewardsMap = indexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.reduce( - (acc, cur) => { - acc[cur.keys[0]] = cur.sum; - return acc; - }, - {} as Record, - ); - - return allIndexers.data.indexers.nodes.map((indexer) => { - const indexerRewards = indexerRewardsMap[indexer.id]; - const apy = indexerRewardsInfos.data?.eraIndexerApies.nodes.find( - (node) => node.indexerId === indexer.id, - )?.indexerApy; - - const totalStake = parseRawEraValue(indexer.totalStake, selectEra).current.toString(); - const selfStake = parseRawEraValue(indexer.selfStake, selectEra).current.toString(); - const queries = queriesOfAllIndexers.data?.find((i) => i.user.toLowerCase() === indexer.id.toLowerCase()); - - return { - ...indexer, - totalStake: formatNumber(formatSQT(totalStake || '0')), - selfStake: formatNumber(formatSQT(selfStake || '0')), - delegationStake: formatNumber(formatSQT(BigNumberJs(totalStake).minus(selfStake).toString())), - allocationRewards: formatNumber(formatSQT(BigNumberJs(indexerRewards?.allocationRewards || 0).toString())), - queryRewards: formatNumber(formatSQT(BigNumberJs(indexerRewards?.queryRewards || 0).toString())), - queries: BigNumberJs(queries?.info.total || 0) - .div(10 ** 15) - .toFixed(0), - apy: BigNumberJs(formatSQT(apy || '0')) - .multipliedBy(100) - .toFixed(2), - }; - }); - }, [allIndexers.data, indexerRewardsInfos.data, selectEra, queriesOfAllIndexers]); - - const previousRenderData = usePrevious(renderData); - - useEffect(() => { - if (currentEra.data?.index) { - setSelectEra(currentEra.data?.index - 1); - } - }, [currentEra.data?.index]); - - return ( -
-
-
- - Node Operators ({allIndexers.data?.indexers.totalCount ?? allIndexers.previousData?.indexers.totalCount}) - -
- -
- - } - onChange={(e) => { - debounceSearch(e.target.value); - }} - > -
- - record.id} - className={'darkTable'} - loading={allIndexers.loading || indexerRewardsInfos.loading} - columns={[ - { - title: 'Node Operators', - dataIndex: 'name', - key: 'name', - render: (_, record) => { - return ( - { - navigate(`/node-operator/${record.id}`); - }} - /> - ); - }, - }, - { - title: 'apy', - dataIndex: 'apy', - key: 'apy', - render: (text: string) => {text} %, - }, - { - title: 'Stake', - dataIndex: 'totalStake', - key: 'totalStake', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Self Stake', - dataIndex: 'selfStake', - key: 'selfStake', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Stake Rewards', - dataIndex: 'allocationRewards', - key: 'allocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Total Query Rewards', - dataIndex: 'queryRewards', - key: 'queryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Queries', - dataIndex: 'queries', - key: 'queries', - render: (text: string) => {formatNumber(text, 0)}, - }, - { - title: 'Delegation', - dataIndex: 'delegationStake', - key: 'delegationStake', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - ]} - dataSource={renderData?.length ? renderData : previousRenderData} - pagination={{ - total: allIndexers.data?.indexers.totalCount || allIndexers.previousData?.indexers.totalCount, - pageSize: pageInfo.pageSize, - pageSizeOptions: ['10', '30', '50', '100'], - current: pageInfo.currentPage, - onChange(page, pageSize) { - setPageInfo({ - pageSize, - currentPage: page, - }); - }, - }} - >
-
-
- ); -}; -export default ScannerDashboard; diff --git a/src/pages/scanner/projectDeploymentRewards/index.module.less b/src/pages/scanner/projectDeploymentRewards/index.module.less deleted file mode 100644 index a9e65c36..00000000 --- a/src/pages/scanner/projectDeploymentRewards/index.module.less +++ /dev/null @@ -1,18 +0,0 @@ -.dashboard { - padding: 24px; - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - gap: 24px; - - &Inner { - padding: 24px; - border: 1px solid var(--dark-mode-border); - border-radius: 8px; - height: 100%; - width: 100%; - flex: 1; - background: var(--dark-mode-card); - } -} \ No newline at end of file diff --git a/src/pages/scanner/projectDeploymentRewards/index.tsx b/src/pages/scanner/projectDeploymentRewards/index.tsx deleted file mode 100644 index 9c574af1..00000000 --- a/src/pages/scanner/projectDeploymentRewards/index.tsx +++ /dev/null @@ -1,727 +0,0 @@ -import React, { FC, useEffect, useMemo, useState } from 'react'; -import { IoSearch } from 'react-icons/io5'; -import { useNavigate } from 'react-router'; -import { gql, useLazyQuery, useQuery } from '@apollo/client'; -import { DeploymentMeta } from '@components'; -import { useEra } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { Typography } from '@subql/components'; -import { useAsyncMemo } from '@subql/react-hooks'; -import { TOKEN } from '@utils'; -import { Button, Input, Radio, Select, Table, Tooltip } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import dayjs from 'dayjs'; -import { parseEther } from 'ethers/lib/utils'; -import { t } from 'i18next'; -import { debounce } from 'lodash-es'; - -import { formatNumber, formatSQT } from '../../../utils/numberFormatters'; -import styles from './index.module.less'; - -interface IProps {} - -const ScannerDashboard: FC = (props) => { - const { currentEra } = useEra(); - const navigate = useNavigate(); - const { getStatisticQueries } = useConsumerHostServices({ - autoLogin: false, - }); - const [selectEra, setSelectEra] = useState((currentEra.data?.index || 1) - 1 || 0); - const [pageInfo, setPageInfo] = useState({ - pageSize: 30, - currentPage: 1, - }); - const [calcInput, setCalcInput] = useState(100000); - const [rowSelected, setRowSelected] = useState<{ deploymentId: string }>(); - const [statisticGroup, setStatisticGroup] = useState<'averageRewards' | 'projectedRewards'>('averageRewards'); - const [searchDeployment, setSearchDeployment] = useState(''); - const debounceSearch = useMemo(() => debounce(setSearchDeployment, 500), [setSearchDeployment]); - const blockHeightOfQuery = useMemo(() => { - if (!currentEra.data?.index) return '99999999999999999'; - - if (selectEra === currentEra.data.index - 1 || selectEra === currentEra.data.index) { - return '99999999999999999'; - } - - return currentEra.data.eras?.find((i) => parseInt(i.id, 16) === selectEra)?.createdBlock || '99999999999999999'; - }, [selectEra, currentEra.data?.index]); - - const [fetchAllDeployments] = useLazyQuery<{ - eraDeploymentRewards: { - nodes: { deploymentId: string; totalRewards: string }[]; - totalCount: number; - }; - }>( - gql` - query allDeployments($deploymentId: String = "", $currentIdx: Int!, $first: Int! = 30, $offset: Int! = 0) { - eraDeploymentRewards( - orderBy: TOTAL_REWARDS_DESC - filter: { eraIdx: { equalTo: $currentIdx }, deploymentId: { includesInsensitive: $deploymentId } } - first: $first - offset: $offset - ) { - nodes { - deploymentId - totalRewards - } - totalCount - } - } - `, - { - variables: { - currentIdx: selectEra, - first: pageInfo.pageSize, - offset: (pageInfo.currentPage - 1) * pageInfo.pageSize, - deploymentId: searchDeployment, - }, - }, - ); - - const [fetchAllDeploymentsInfomations] = useLazyQuery<{ - deployments: { - nodes: { - id: string; - metadata: string; - project: { - id: string; - metadata: string; - }; - indexers: { - totalCount: number; - }; - }[]; - }; - indexerAllocationSummaries: { - groupedAggregates: { keys: string[]; sum: { totalAmount: string } }[]; - }; - deploymentBoosterSummaries: { - groupedAggregates: { keys: string[]; sum: { totalAmount: string } }[]; - }; - eraDeploymentRewards: { - groupedAggregates: { keys: string[]; sum: { allocationRewards: string; totalRewards: string } }[]; - }; - }>(gql` - query allDeploymentsInfomations($blockHeight: String!, $deploymentIds: [String!], $currentIdx: Int!) { - deployments(blockHeight: $blockHeight, filter: { id: { in: $deploymentIds } }) { - nodes { - id - metadata - project { - id - metadata - } - indexers(filter: { indexer: { active: { equalTo: true } }, status: { notEqualTo: TERMINATED } }) { - totalCount - } - } - } - - indexerAllocationSummaries(blockHeight: $blockHeight, filter: { deploymentId: { in: $deploymentIds } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - totalAmount - } - } - } - - deploymentBoosterSummaries(blockHeight: $blockHeight, filter: { deploymentId: { in: $deploymentIds } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - totalAmount - } - } - } - - eraDeploymentRewards(filter: { deploymentId: { in: $deploymentIds }, eraIdx: { equalTo: $currentIdx } }) { - groupedAggregates(groupBy: DEPLOYMENT_ID) { - keys - sum { - allocationRewards - totalRewards - } - } - } - } - `); - - const allDeployments = useAsyncMemo(async () => { - if (!selectEra) return { nodes: [], totalCount: 0 }; - let currentOffset = 0; - const res = await fetchAllDeployments({ - variables: { - currentIdx: selectEra, - first: 100, - offset: 0, - deploymentId: '', - }, - }); - - const result = res.data?.eraDeploymentRewards || { nodes: [], totalCount: 0 }; - const resultTotal = res.data?.eraDeploymentRewards.totalCount || 0; - while (currentOffset < resultTotal) { - currentOffset += 100; - const res = await fetchAllDeployments({ - variables: { - currentIdx: selectEra, - first: 100, - offset: currentOffset, - deploymentId: '', - }, - }); - - result.nodes = result.nodes.concat(res.data?.eraDeploymentRewards.nodes || []); - } - - return result; - }, [selectEra]); - - const allDeploymentsInfomations = useAsyncMemo(async () => { - if (!allDeployments.data?.nodes.length) - return { - deployments: { nodes: [] }, - indexerAllocationSummaries: { groupedAggregates: [] }, - deploymentBoosterSummaries: { groupedAggregates: [] }, - eraDeploymentRewards: { groupedAggregates: [] }, - }; - const deploymentIds = allDeployments.data?.nodes.map((node) => node.deploymentId); - - const chunkedDeploymentIds: string[][] = []; - for (let i = 0; i < deploymentIds.length; i += 100) { - chunkedDeploymentIds.push(deploymentIds.slice(i, i + 100)); - } - - const results = await Promise.all( - chunkedDeploymentIds.map((chunk) => - fetchAllDeploymentsInfomations({ - variables: { - deploymentIds: chunk, - currentIdx: selectEra, - blockHeight: blockHeightOfQuery.toString(), - }, - }), - ), - ); - - // Combine results from all chunks - return results.reduce( - ( - acc: { - deployments: { nodes: any[] }; - indexerAllocationSummaries: { groupedAggregates: any[] }; - deploymentBoosterSummaries: { groupedAggregates: any[] }; - eraDeploymentRewards: { groupedAggregates: any[] }; - }, - result, - ) => { - if (result.data) { - acc.deploymentBoosterSummaries.groupedAggregates = [ - ...acc.deploymentBoosterSummaries.groupedAggregates, - ...result.data.deploymentBoosterSummaries.groupedAggregates, - ]; - acc.deployments.nodes = [...acc.deployments.nodes, ...result.data.deployments.nodes]; - acc.indexerAllocationSummaries.groupedAggregates = [ - ...acc.indexerAllocationSummaries.groupedAggregates, - ...result.data.indexerAllocationSummaries.groupedAggregates, - ]; - acc.eraDeploymentRewards.groupedAggregates = [ - ...acc.eraDeploymentRewards.groupedAggregates, - ...result.data.eraDeploymentRewards.groupedAggregates, - ]; - } - - return acc; - }, - { - deployments: { nodes: [] }, - indexerAllocationSummaries: { groupedAggregates: [] }, - deploymentBoosterSummaries: { groupedAggregates: [] }, - eraDeploymentRewards: { groupedAggregates: [] }, - }, - ); - }, [allDeployments.data]); - - const queries = useAsyncMemo(async () => { - if (!currentEra.data) return []; - const deployments = allDeployments.data?.nodes.map((i) => i.deploymentId); - if (!deployments || !deployments?.length) return []; - const selectedEra = currentEra.data?.eras?.find((i) => parseInt(i.id, 16) === selectEra); - try { - const res = await getStatisticQueries({ - deployment: deployments, - start_date: dayjs(selectedEra?.startTime).format('YYYY-MM-DD'), - end_date: selectedEra?.endTime ? dayjs(selectedEra?.endTime).format('YYYY-MM-DD') : undefined, - }); - - return res.data.list; - } catch (e) { - return []; - } - }, [allDeployments.data, selectEra]); - - const renderData = useMemo(() => { - if (selectEra === 0) return []; - if (allDeployments.loading) return []; - - if (allDeployments.data?.totalCount && !allDeploymentsInfomations.data?.deployments?.nodes?.length) return []; - if (!allDeployments.data?.nodes.length) return []; - - return allDeployments.data?.nodes - .map((node) => { - const inputStake = BigNumberJs(calcInput).gt(100000000) ? '100000000' : calcInput; - const eraDeploymentRewardsItem = allDeploymentsInfomations.data?.eraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - ); - - const rawTotalStake = BigNumberJs( - allDeploymentsInfomations.data?.indexerAllocationSummaries.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - )?.sum.totalAmount || '0', - ); - - const rawTotalRewards = BigNumberJs(eraDeploymentRewardsItem?.sum.allocationRewards || '0'); - - const estimatedRewardsOfInputStake = rawTotalRewards.multipliedBy( - BigNumberJs(parseEther(inputStake.toString()).toString()).div( - rawTotalStake.plus(parseEther(inputStake.toString()).toString()), - ), - ); - - const totalCount = - (allDeploymentsInfomations.data?.deployments.nodes.find((i) => i.id === node.deploymentId)?.indexers - .totalCount || 0) + (statisticGroup === 'averageRewards' ? 0 : 1); - - const totalAllocation = rawTotalStake - .plus(statisticGroup === 'averageRewards' ? 0 : parseEther(inputStake.toString()).toString()) - .toString(); - - const allocationRewards = - statisticGroup === 'projectedRewards' - ? estimatedRewardsOfInputStake.toString() - : eraDeploymentRewardsItem?.sum.allocationRewards || '0'; - - const totalQueryRewards = BigNumberJs(eraDeploymentRewardsItem?.sum.totalRewards || '0') - .minus(eraDeploymentRewardsItem?.sum.allocationRewards || '0') - .toFixed(); - const deploymentInfo = allDeploymentsInfomations.data?.deployments.nodes.find( - (i) => i.id === node.deploymentId, - ); - const allocationApy = BigNumberJs(allocationRewards || 0) - .div(statisticGroup === 'averageRewards' ? totalAllocation : parseEther(inputStake.toString()).toString()) - .multipliedBy(52) - .multipliedBy(100); - - const deploymentQueryCount = queries.data?.find((i) => i.deployment === node.deploymentId); - - return { - deploymentId: node.deploymentId, - projectMetadata: deploymentInfo?.project.metadata, - projectId: deploymentInfo?.project.id, - operatorCount: totalCount, - rawAllocationAmount: totalAllocation, - rawAllocationRewards: allocationRewards, - rawBooster: formatSQT( - allDeploymentsInfomations.data?.deploymentBoosterSummaries.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - )?.sum.totalAmount || '0', - ), - allocationAmount: formatNumber(formatSQT(totalAllocation)), - boosterAmount: formatNumber( - formatSQT( - allDeploymentsInfomations.data?.deploymentBoosterSummaries.groupedAggregates.find( - (i) => i.keys[0] === node.deploymentId, - )?.sum.totalAmount || '0', - ), - ), - allocationRewards: formatNumber(formatSQT(allocationRewards)), - averageAllocationRewards: formatNumber( - formatSQT( - BigNumberJs(allocationRewards) - .div(totalCount || 1) - .toFixed(), - ), - ), - allocationApy: allocationApy.isNaN() ? '0.00' : allocationApy.gt(1000) ? '1000+' : allocationApy.toFixed(2), - rawAllocationApy: allocationApy.isNaN() ? '0.00' : allocationApy.toFixed(2), - queryRewards: formatNumber(formatSQT(totalQueryRewards)), - averageQueryRewards: formatNumber( - formatSQT( - BigNumberJs(totalQueryRewards) - .div(totalCount || 1) - .toFixed(), - ), - ), - rawAverageQueryRewards: formatSQT( - BigNumberJs(totalQueryRewards) - .div(totalCount || 1) - .toFixed(), - ), - totalRewards: formatNumber(formatSQT(BigNumberJs(allocationRewards).plus(totalQueryRewards).toString())), - averageRewards: formatNumber( - formatSQT( - BigNumberJs(eraDeploymentRewardsItem?.sum.totalRewards || '0') - .div(totalCount || 1) - .toFixed(), - ), - ), - rawAverageRewards: formatSQT( - BigNumberJs(eraDeploymentRewardsItem?.sum.totalRewards || '0') - .div(totalCount || 1) - .toFixed(), - ), - averageQueriesCount: formatNumber( - BigNumberJs(deploymentQueryCount?.queries || '0') - .div(totalCount || 1) - .toString(), - 0, - ), - }; - }) - .filter((i) => i.deploymentId.toLowerCase().includes(searchDeployment.toLowerCase())); - }, [allDeployments, allDeploymentsInfomations, calcInput, statisticGroup, queries.data, searchDeployment, selectEra]); - - const estimatedStakeRewards = useMemo(() => { - const selectedRow = renderData?.find((i) => i.deploymentId === rowSelected?.deploymentId); - if (!selectedRow) { - return 0; - } - - const { rawAllocationAmount, rawAllocationRewards } = selectedRow; - if (BigNumberJs(rawAllocationAmount).isZero()) { - return 0; - } - const oneTokenRewards = BigNumberJs(rawAllocationRewards).div( - rawAllocationAmount === '0' ? 1 : rawAllocationAmount, - ); - const result = oneTokenRewards.multipliedBy(calcInput).toFixed(6); - if (isNaN(+result)) { - return '0.000000'; - } - return result; - }, [rowSelected, calcInput]); - - useEffect(() => { - if (currentEra.data?.index) { - setSelectEra(currentEra.data?.index - 1); - } - }, [currentEra.data?.index]); - - return ( -
-
-
- - Project Deployment Rewards - -
- -
- { - setStatisticGroup(val.target.value); - }} - value={statisticGroup} - optionType="button" - buttonStyle="solid" - /> - - } - onChange={(e) => { - debounceSearch(e.target.value); - }} - > -
- {statisticGroup === 'projectedRewards' ? ( -
-
- Projected Rewards Calculator - - Estimated Rewards One Era:

- {estimatedStakeRewards} {TOKEN} -
-
- -
- Enter Your Stake - {TOKEN}} - value={calcInput} - onChange={(e) => { - if (Number(e.target.value) > 100000000) { - setCalcInput(100000000); - return; - } - - setCalcInput(Number(e.target.value)); - }} - onBlur={(e) => { - if (Number(e.target.value) < 1) { - setCalcInput(1); - return; - } - }} - min="1" - max={100000000} - > -
-
- ) : ( - '' - )} - - record.deploymentId} - className={'darkTable'} - loading={allDeployments.loading || allDeploymentsInfomations.loading} - columns={[ - { - title: 'Project', - dataIndex: 'name', - key: 'name', - render: (_: string, record: (typeof renderData)[number]) => { - return ; - }, - onCell: (record: (typeof renderData)[number]) => { - return { - onClick: () => { - navigate( - `/project-deployment-rewards/${record.deploymentId}?projectMetadata=${record.projectMetadata}&projectId=${record.projectId}`, - ); - }, - }; - }, - }, - { - title: Node Operators, - dataIndex: 'operatorCount', - key: 'operatorCount', - render: (text: number) => {text}, - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.operatorCount).comparedTo(b.operatorCount); - }, - }, - { - title: statisticGroup === 'averageRewards' ? 'Stake' : 'Projected Total Stake', - dataIndex: 'allocationAmount', - key: 'allocationAmount', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAllocationAmount).comparedTo(b.rawAllocationAmount); - }, - }, - { - title: 'Boost', - dataIndex: 'boosterAmount', - key: 'boosterAmount', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawBooster).comparedTo(b.rawBooster); - }, - }, - { - title: Projected Stake Rewards, - dataIndex: 'allocationRewards', - key: 'allocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAllocationRewards).comparedTo(b.rawAllocationRewards); - }, - }, - { - title: 'Average Stake Rewards', - dataIndex: 'averageAllocationRewards', - key: 'averageAllocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAllocationRewards).comparedTo(b.rawAllocationRewards); - }, - }, - { - title: - statisticGroup === 'averageRewards' ? ( - 'Stake Apy' - ) : ( - Projected Stake APY - ), - dataIndex: 'allocationApy', - key: 'allocationApy', - render: (text: string) => {text} %, - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAllocationApy).comparedTo(b.rawAllocationApy); - }, - }, - { - title: 'Average Queries', - dataIndex: 'averageQueriesCount', - key: 'averageQueriesCount', - render: (text: string) => {text}, - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.averageQueriesCount).comparedTo(b.averageQueriesCount); - }, - }, - { - title: 'Projected Query Rewards', - dataIndex: 'queryRewards', - key: 'queryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Average Query Rewards', - dataIndex: 'averageQueryRewards', - key: 'averageQueryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAverageQueryRewards).comparedTo(b.rawAverageQueryRewards); - }, - }, - { - title: 'Projected Rewards', - dataIndex: 'totalRewards', - key: 'totalRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - }, - { - title: 'Average Rewards', - dataIndex: 'averageRewards', - key: 'averageRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAverageRewards).comparedTo(b.rawAverageRewards); - }, - }, - ].filter((i) => { - const keysOfAver = [ - 'name', - 'operatorCount', - 'allocationAmount', - 'boosterAmount', - 'averageAllocationRewards', - 'allocationApy', - 'averageQueriesCount', - 'averageQueryRewards', - 'averageRewards', - ]; - const keysOfProj = [ - 'name', - 'operatorCount', - 'allocationAmount', - 'boosterAmount', - 'allocationRewards', - 'allocationApy', - 'queryRewards', - 'totalRewards', - ]; - - if (statisticGroup === 'averageRewards') { - return keysOfAver.includes(i.dataIndex); - } else { - return keysOfProj.includes(i.dataIndex); - } - })} - dataSource={renderData} - pagination={{ - total: allDeployments.data?.nodes.length, - pageSize: pageInfo.pageSize, - pageSizeOptions: ['10', '30', '50', '100'], - current: pageInfo.currentPage, - onChange(page, pageSize) { - setPageInfo({ - pageSize, - currentPage: page, - }); - }, - }} - rowSelection={{ - type: 'radio', - hideSelectAll: true, - selectedRowKeys: rowSelected ? [rowSelected.deploymentId] : [], - onChange: (_, row) => { - setRowSelected({ - deploymentId: row[0].deploymentId, - }); - }, - }} - onRow={(record) => { - return { - onClick: () => { - setRowSelected({ - deploymentId: record.deploymentId, - }); - }, - }; - }} - >
-
-
- ); -}; -export default ScannerDashboard; diff --git a/src/pages/scanner/projectDetail/components/priceQueries/priceQueries.tsx b/src/pages/scanner/projectDetail/components/priceQueries/priceQueries.tsx deleted file mode 100644 index d74e2d71..00000000 --- a/src/pages/scanner/projectDetail/components/priceQueries/priceQueries.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import { CSSProperties } from 'react'; -import BarCharts from '@components/BarCharts'; -import { useEra } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { Typography } from '@subql/components'; -import { useAsyncMemo } from '@subql/react-hooks'; -import { formatNumber, formatSQT, parseError, renderAsync } from '@utils'; -import { Skeleton } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import dayjs from 'dayjs'; - -export const PriceQueriesChart = (props: { - title?: string; - dataDimensionsName?: string[]; - chartsStyle?: CSSProperties; - skeletonHeight?: number; - deploymentId?: string; - indexerAddress?: string; -}) => { - const { title = 'Queries by Price', chartsStyle, skeletonHeight, deploymentId } = props; - const { currentEra } = useEra(); - - const { getStatisticQueriesByPrice } = useConsumerHostServices({ - autoLogin: false, - }); - - const statisticPrice = useAsyncMemo(async () => { - if (!deploymentId || !currentEra.data) - return new Array(10).fill(0).map((_, i) => ({ price: `${0.5 * (i + 1)}`, queries: 0 })); - const res = await getStatisticQueriesByPrice({ - deployment: [deploymentId], - start_date: dayjs(currentEra.data?.eras?.at(1)?.startTime).format('YYYY-MM-DD'), - end_date: currentEra.data?.eras?.at(1)?.endTime - ? dayjs(currentEra.data?.eras?.at(1)?.endTime).format('YYYY-MM-DD') - : undefined, - }); - - let rawData = res.data.sort((a, b) => BigNumberJs(a.price || 0).comparedTo(b.price || 0)); - const limitLength = 10; - if (rawData.length > limitLength) { - rawData = rawData.sort((a, b) => BigNumberJs(a.count || 0).comparedTo(b.count || 0)).slice(limitLength); - } - - if (rawData.length < limitLength) { - const lastPrice = BigNumberJs(rawData.at(-1)?.price || '0'); - rawData = [ - ...rawData, - ...new Array(limitLength - rawData.length).fill(0).map((_, i) => ({ - price: lastPrice.plus(BigNumberJs(0.5 * (i + 1)).multipliedBy(10 ** 15)).toFixed(), - queries: 0, - })), - ]; - } - - return rawData.map((i) => { - return { - price: formatSQT( - BigNumberJs(i.price || '0') - .multipliedBy(1000) - .toFixed(2), - { - fixedNum: 2, - }, - ) as string, - queries: i.count, - }; - }); - }, [deploymentId, currentEra.data]); - - return renderAsync(statisticPrice, { - loading: () => ( - - ), - error: (e) => { - console.warn(e); - return {parseError(e)}; - }, - data: () => { - return ( - i.price) || [], - }} - title={title} - suffix={`Price Range (SQT per 1,000 queries)`} - chartData={statisticPrice.data ? [statisticPrice.data?.map((i) => i.queries || 0)] : []} - onTriggerTooltip={(index) => { - return `
-
- Total - ${formatNumber(statisticPrice.data?.[index].queries || 0)} -
-
`; - }} - customColors={['#4388DD', '#65CD45']} - >
- ); - }, - }); -}; diff --git a/src/pages/scanner/projectDetail/components/rewardsByType/rewardsByType.tsx b/src/pages/scanner/projectDetail/components/rewardsByType/rewardsByType.tsx deleted file mode 100644 index b7b46f6a..00000000 --- a/src/pages/scanner/projectDetail/components/rewardsByType/rewardsByType.tsx +++ /dev/null @@ -1,220 +0,0 @@ -import { CSSProperties, useEffect, useMemo, useState } from 'react'; -import { gql, useLazyQuery } from '@apollo/client'; -import LineCharts, { FilterType, xAxisScalesFunc } from '@components/LineCharts'; -import { useEra } from '@hooks'; -import { getSplitDataByEra } from '@pages/dashboard/components/RewardsLineChart/RewardsLineChart'; -import { Typography } from '@subql/components'; -import { formatNumber, numToHex, parseError, renderAsync, TOKEN, toPercentage } from '@utils'; -import { Skeleton } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import dayjs from 'dayjs'; - -export const RewardsByType = (props: { - title?: string; - dataDimensionsName?: string[]; - chartsStyle?: CSSProperties; - skeletonHeight?: number; - deploymentId?: string; - indexerAddress?: string; -}) => { - const { - title = 'Rewards by Type', - dataDimensionsName = ['Stake Rewards', 'Query Rewards'], - chartsStyle, - skeletonHeight, - deploymentId, - indexerAddress, - } = props; - const { currentEra } = useEra(); - const [filter, setFilter] = useState({ date: 'lm' }); - const [renderRewards, setRenderRewards] = useState([[]]); - const [rawRewardsData, setRawRewardsData] = useState<{ allocation: number[]; query: number[]; total: number[] }>({ - allocation: [], - query: [], - total: [], - }); - - const rewardsLineXScales = useMemo(() => { - const getXScales = (period: number, filterVal: FilterType) => { - const getDefaultScales = xAxisScalesFunc(period); - - const result = getDefaultScales[filterVal.date](); - return result.slice(0, result.length - 1); - }; - const slicedResult = getXScales(currentEra.data?.period || 0, filter); - return { - val: { - renderData: slicedResult.map((i) => i.format('MMM D')), - rawData: slicedResult, - }, - getXScales, - }; - }, [filter.date, currentEra]); - - const [fetchRewards, rewardsData] = useLazyQuery<{ - eraDeploymentRewards: { - groupedAggregates: { keys: string[]; sum: { allocationRewards: string; totalRewards: string } }[]; - }; - indexerEraDeploymentRewards: { - groupedAggregates: { keys: string[]; sum: { allocationRewards: string; totalRewards: string } }[]; - }; - }>(gql` - query fetchRewards($deploymentId: String! = "0", $eraIds: [Int!]!, $indexer: String! = "") { - eraDeploymentRewards(filter: { deploymentId: { equalTo: $deploymentId }, eraIdx: { in: $eraIds } }) { - groupedAggregates(groupBy: ERA_IDX) { - keys - sum { - allocationRewards - totalRewards - } - } - } - - indexerEraDeploymentRewards(filter: { indexerId: { equalTo: $indexer }, eraIdx: { in: $eraIds } }) { - groupedAggregates(groupBy: ERA_IDX) { - keys - sum { - allocationRewards - totalRewards - } - } - } - } - `); - - const fetchRewardsByEra = async (filterVal: FilterType | undefined = filter) => { - if (!currentEra.data) return; - if (!filterVal) return; - const { getIncludesEras, fillData } = getSplitDataByEra(currentEra.data); - const { includesEras, includesErasHex } = { - lm: () => getIncludesEras(dayjs().subtract(31, 'day')), - l3m: () => getIncludesEras(dayjs().subtract(90, 'day')), - ly: () => getIncludesEras(dayjs().subtract(365, 'day')), - }[filterVal.date](); - const apis = fetchRewards; - const vars = { - eraIds: includesEras, - deploymentId: deploymentId, - indexer: indexerAddress, - }; - const res = await apis({ - variables: vars, - fetchPolicy: 'no-cache', - }); - - const maxPaddingLength = rewardsLineXScales.getXScales(currentEra.data.period, filterVal).length; - - // // rewards don't want to show lastest era data - const removedLastEras = includesErasHex.slice(1, includesErasHex.length); - const curry = ['0']>(data: T) => - fillData(data, removedLastEras, maxPaddingLength); - - const dataSource = indexerAddress ? res?.data?.indexerEraDeploymentRewards : res?.data?.eraDeploymentRewards; - - const allocationRewards = curry( - dataSource?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - - sum: { - amount: i.sum.allocationRewards, - }, - }; - }) || [], - ); - - const queryRewards = curry( - dataSource?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - - sum: { - amount: BigNumberJs(i.sum.totalRewards).minus(i.sum.allocationRewards).toString(), - }, - }; - }) || [], - ); - - const totalRewards = curry( - dataSource?.groupedAggregates?.map((i) => { - return { - keys: i.keys.map((i) => numToHex(+i)), - sum: { - amount: i.sum.totalRewards, - }, - }; - }) || [], - ); - setRawRewardsData({ - allocation: allocationRewards, - query: queryRewards, - total: totalRewards, - }); - - setRenderRewards([allocationRewards, queryRewards]); - }; - - useEffect(() => { - fetchRewardsByEra(); - }, [currentEra.data?.index, deploymentId]); - - return renderAsync( - { - ...rewardsData, - loading: rewardsData.previousData ? false : rewardsData.loading, - data: rewardsData.data || rewardsData.previousData, - }, - { - loading: () => ( - - ), - error: (e) => {parseError(e)}, - data: () => { - return ( - { - setFilter(val); - fetchRewardsByEra(val); - }} - style={chartsStyle} - xAxisScales={rewardsLineXScales.val} - title={title} - dataDimensionsName={dataDimensionsName} - chartData={renderRewards} - onTriggerTooltip={(index, curDate) => { - return `
- ${curDate.format('MMM D, YYYY')} -
- Total - ${formatNumber(rawRewardsData.total[index])} ${TOKEN} -
-
- ${dataDimensionsName[0]} - ${formatNumber(rawRewardsData.allocation[index])} ${TOKEN} (${toPercentage( - rawRewardsData.allocation[index], - rawRewardsData.total[index], - )}) -
-
- ${dataDimensionsName[1]} - ${formatNumber(rawRewardsData.query[index])} ${TOKEN} (${toPercentage( - rawRewardsData.query[index], - rawRewardsData.total[index], - )}) -
-
`; - }} - customColors={['#4388DD', '#65CD45']} - >
- ); - }, - }, - ); -}; diff --git a/src/pages/scanner/projectDetail/index.module.less b/src/pages/scanner/projectDetail/index.module.less deleted file mode 100644 index a9e65c36..00000000 --- a/src/pages/scanner/projectDetail/index.module.less +++ /dev/null @@ -1,18 +0,0 @@ -.dashboard { - padding: 24px; - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - gap: 24px; - - &Inner { - padding: 24px; - border: 1px solid var(--dark-mode-border); - border-radius: 8px; - height: 100%; - width: 100%; - flex: 1; - background: var(--dark-mode-card); - } -} \ No newline at end of file diff --git a/src/pages/scanner/projectDetail/index.tsx b/src/pages/scanner/projectDetail/index.tsx deleted file mode 100644 index 9c1361f7..00000000 --- a/src/pages/scanner/projectDetail/index.tsx +++ /dev/null @@ -1,576 +0,0 @@ -import React, { FC, useEffect, useMemo, useState } from 'react'; -import { useNavigate, useParams } from 'react-router'; -import { useSearchParams } from 'react-router-dom'; -import { gql, useQuery } from '@apollo/client'; -import { DeploymentMeta } from '@components'; -import { IndexerName } from '@components/IndexerDetails/IndexerName'; -import { useProjectMetadata } from '@containers'; -import { useAsyncMemo, useEra } from '@hooks'; -import { useConsumerHostServices } from '@hooks/useConsumerHostServices'; -import { Typography } from '@subql/components'; -import { TOKEN } from '@utils'; -import { usePrevious } from 'ahooks'; -import { Breadcrumb, Button, Table } from 'antd'; -import BigNumberJs from 'bignumber.js'; -import clsx from 'clsx'; -import dayjs from 'dayjs'; - -import { formatNumber, formatSQT } from '../../../utils/numberFormatters'; -import { PriceQueriesChart } from './components/priceQueries/priceQueries'; -import { RewardsByType } from './components/rewardsByType/rewardsByType'; -import styles from './index.module.less'; - -interface IProps {} - -const ProjectDetail: FC = (props) => { - const { currentEra } = useEra(); - const navigate = useNavigate(); - const { id: deploymentId } = useParams(); - const [query] = useSearchParams(); - const { getProjects, getStatisticQueriesByPrice, getStatisticQueries } = useConsumerHostServices({ - autoLogin: false, - }); - const { getMetadataFromCid } = useProjectMetadata(); - - const metadata = useAsyncMemo(async () => { - if (!query.get('projectMetadata')) return null; - return await getMetadataFromCid(query.get('projectMetadata') || ''); - }, [query]); - - const [selectEra, setSelectEra] = useState((currentEra.data?.index || 1) - 1 || 0); - const [pageInfo, setPageInfo] = useState({ - pageSize: 100, - currentPage: 1, - }); - const deploymentInfomations = useQuery<{ - eraDeploymentRewards: { - aggregates: { - sum: { - allocationRewards: string; - totalRewards: string; - }; - }; - }; - deployment: { - indexers: { - totalCount: number; - nodes: { - indexerId: string; - }[]; - }; - projectId: string; - }; - }>( - gql` - query deploymentInfomations($deploymentId: String!, $first: Int! = 30, $offset: Int! = 0) { - eraDeploymentRewards(filter: { deploymentId: { equalTo: $deploymentId } }) { - aggregates { - sum { - allocationRewards - totalRewards - } - } - } - - deployment(id: $deploymentId) { - indexers( - first: $first - offset: $offset - filter: { indexer: { active: { equalTo: true } }, status: { notEqualTo: TERMINATED } } - ) { - totalCount - nodes { - indexerId - } - } - projectId - } - } - `, - { - variables: { - deploymentId, - first: pageInfo.pageSize, - offset: (pageInfo.currentPage - 1) * pageInfo.pageSize, - }, - }, - ); - - const deploymentIndexerRewardsInfos = useQuery<{ - indexerAllocationRewards: { - groupedAggregates: { - sum: { - burnt: string; - }; - keys: string[]; - }[]; - }; - indexerAllocationSummaries: { - nodes: { - indexerId: string; - totalAmount: string; - }[]; - }; - eraIndexerDeploymentApies: { - nodes: { - apy: string; - indexerId: string; - }[]; - }; - indexerEraDeploymentRewards: { - groupedAggregates: { - sum: { - allocationRewards: string; - queryRewards: string; - totalRewards: string; - }; - keys: string[]; - }[]; - }; - }>( - gql` - query getDeoloymentIndexerRewardsInfos($indexerIds: [String!], $deploymentId: String!, $eraIdx: Int!) { - indexerAllocationRewards(filter: { indexerId: { in: $indexerIds }, deploymentId: { equalTo: $deploymentId } }) { - groupedAggregates(groupBy: INDEXER_ID) { - sum { - burnt - } - keys - } - } - - indexerAllocationSummaries( - filter: { indexerId: { in: $indexerIds }, deploymentId: { equalTo: $deploymentId } } - ) { - nodes { - indexerId - totalAmount - } - } - - eraIndexerDeploymentApies( - filter: { - indexerId: { in: $indexerIds } - eraIdx: { equalTo: $eraIdx } - deploymentId: { equalTo: $deploymentId } - } - ) { - nodes { - apy - indexerId - } - } - - indexerEraDeploymentRewards( - filter: { indexerId: { in: $indexerIds }, deploymentId: { equalTo: $deploymentId } } - ) { - groupedAggregates(groupBy: INDEXER_ID) { - sum { - allocationRewards - queryRewards - totalRewards - } - keys - } - } - } - `, - { - variables: { - indexerIds: deploymentInfomations.data?.deployment.indexers.nodes.map((i) => i.indexerId) || [], - deploymentId, - eraIdx: selectEra, - }, - }, - ); - - const priceOfIndexers = useAsyncMemo(async () => { - const res = await getProjects({ - projectId: `${parseInt(deploymentInfomations.data?.deployment.projectId || '0x00', 16)}`, - deployment: deploymentId, - }); - - return res.data.indexers; - }, [deploymentId, deploymentInfomations.data?.deployment.projectId]); - - const queries = useAsyncMemo(async () => { - if (!currentEra.data || !deploymentId) return []; - const deployments = [deploymentId]; - - const selectedEra = currentEra.data?.eras?.find((i) => parseInt(i.id, 16) === selectEra); - - try { - const res = await getStatisticQueries({ - deployment: deployments, - start_date: dayjs(selectedEra?.startTime).format('YYYY-MM-DD'), - end_date: selectedEra?.endTime ? dayjs(selectedEra?.endTime).format('YYYY-MM-DD') : undefined, - }); - - return res.data.list; - } catch (e) { - return []; - } - }, [deploymentId, currentEra.data?.startTime, selectEra]); - - const renderData = useMemo(() => { - if (!deploymentInfomations.data?.deployment?.indexers?.nodes.length) { - return []; - } - - return deploymentInfomations.data?.deployment?.indexers?.nodes - .map((node) => { - return { - indexerId: node.indexerId, - totalRewards: formatNumber( - formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.totalRewards || '0', - ), - ), - rawTotalRewards: formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.totalRewards || '0', - ), - queryRewards: formatNumber( - formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.queryRewards || '0', - ), - ), - rawQueryRewards: formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.queryRewards || '0', - ), - allocationRewards: formatNumber( - formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.allocationRewards || '0', - ), - ), - rawAllocationRewards: formatSQT( - deploymentIndexerRewardsInfos.data?.indexerEraDeploymentRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.allocationRewards || '0', - ), - apy: BigNumberJs( - formatSQT( - deploymentIndexerRewardsInfos.data?.eraIndexerDeploymentApies.nodes.find( - (i) => i.indexerId === node.indexerId, - )?.apy || '0', - ), - ) - .multipliedBy(100) - .toFixed(2), - totalAmount: formatNumber( - formatSQT( - deploymentIndexerRewardsInfos.data?.indexerAllocationSummaries.nodes.find( - (i) => i.indexerId === node.indexerId, - )?.totalAmount || '0', - ), - ), - rawTotalAmount: formatSQT( - deploymentIndexerRewardsInfos.data?.indexerAllocationSummaries.nodes.find( - (i) => i.indexerId === node.indexerId, - )?.totalAmount || '0', - ), - burnt: formatNumber( - formatSQT( - deploymentIndexerRewardsInfos.data?.indexerAllocationRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.burnt || '0', - ), - ), - rawBurnt: formatSQT( - deploymentIndexerRewardsInfos.data?.indexerAllocationRewards.groupedAggregates.find( - (i) => i.keys[0] === node.indexerId, - )?.sum.burnt || '0', - ), - price: BigNumberJs( - formatSQT(priceOfIndexers.data?.find((i) => i.indexer === node.indexerId.toLowerCase())?.price || '0'), - ) - .multipliedBy(1000) - .toFixed(2), - }; - }) - .sort((a, b) => { - return BigNumberJs(b.rawTotalRewards).comparedTo(a.rawTotalRewards); - }); - }, [deploymentInfomations.data, deploymentIndexerRewardsInfos.data, priceOfIndexers.data]); - - const previousRenderData = usePrevious(renderData); - - useEffect(() => { - if (currentEra.data?.index) { - setSelectEra(currentEra.data?.index - 1); - } - }, [currentEra.data?.index]); - - return ( -
- - Project Deployment Rewards - - ), - onClick: () => { - navigate(`/project-deployment-rewards`); - }, - }, - { - key: 'current', - title: ( - - {metadata.data?.name} - - ), - }, - ]} - > - -
-
- - -
-
- - Project Rewards - - - - {formatNumber( - formatSQT(deploymentInfomations.data?.eraDeploymentRewards.aggregates.sum.totalRewards || '0'), - )}{' '} - {TOKEN} - -
- -
- - Node Operators - - - {deploymentInfomations.data?.deployment.indexers.totalCount} -
- -
- - Stake Rewards - - - - {formatNumber( - formatSQT(deploymentInfomations.data?.eraDeploymentRewards.aggregates.sum.allocationRewards || '0'), - )}{' '} - {TOKEN} - -
- -
- - Query Rewards - - - - {formatNumber( - formatSQT( - BigNumberJs(deploymentInfomations.data?.eraDeploymentRewards.aggregates.sum.totalRewards || '0') - .minus(deploymentInfomations.data?.eraDeploymentRewards.aggregates.sum.allocationRewards || '0') - .toString(), - ), - )}{' '} - {TOKEN} - -
- -
- - Queries - - - - {formatNumber(queries.data?.find((i) => i.deployment === deploymentId)?.queries || 0)} - -
-
-
- - -
-
-
- - Node Operators - {deploymentInfomations.loading && !deploymentInfomations.previousData ? ( - '' - ) : ( - <> - ( - {deploymentInfomations.data?.deployment.indexers.totalCount || - deploymentInfomations.previousData?.deployment.indexers.totalCount} - ) - - )} - -
- - record.indexerId} - className={'darkTable'} - loading={deploymentInfomations.loading || deploymentIndexerRewardsInfos.loading} - columns={[ - { - title: 'Node Operators', - dataIndex: 'indexerId', - key: 'indexerId', - render: (_: string, record: (typeof renderData)[number]) => { - return ; - }, - onCell: (record: (typeof renderData)[number]) => { - return { - onClick: () => { - navigate(`/node-operator/${record.indexerId}`); - }, - }; - }, - }, - { - title: 'Stake', - dataIndex: 'totalAmount', - key: 'totalAmount', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawTotalAmount).comparedTo(b.rawTotalAmount); - }, - }, - { - title: 'Stake Rewards', - dataIndex: 'allocationRewards', - key: 'allocationRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawAllocationRewards).comparedTo(b.rawAllocationRewards); - }, - }, - { - title: 'Query rewards', - dataIndex: 'queryRewards', - key: 'queryRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawQueryRewards).comparedTo(b.rawQueryRewards); - }, - }, - { - title: 'Stake Apy', - dataIndex: 'apy', - key: 'apy', - render: (text: string) => {text} %, - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.apy).comparedTo(b.apy); - }, - }, - { - title: 'Price Per 1,000 Queries', - dataIndex: 'price', - key: 'price', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.price).comparedTo(b.price); - }, - }, - { - title: 'Burned Rewards', - dataIndex: 'burnt', - key: 'burnt', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawBurnt).comparedTo(b.rawBurnt); - }, - }, - { - title: 'Total Rewards', - dataIndex: 'totalRewards', - key: 'totalRewards', - render: (text: string) => ( - - {text} {TOKEN} - - ), - sorter: (a: (typeof renderData)[number], b: (typeof renderData)[number]) => { - return BigNumberJs(a.rawTotalRewards).comparedTo(b.rawTotalRewards); - }, - }, - ]} - dataSource={renderData?.length ? renderData : previousRenderData} - pagination={{ - total: - deploymentInfomations.data?.deployment.indexers.totalCount || - deploymentInfomations.previousData?.deployment.indexers.totalCount, - pageSize: pageInfo.pageSize, - pageSizeOptions: ['10', '30', '50', '100'], - current: pageInfo.currentPage, - onChange(page, pageSize) { - setPageInfo({ - pageSize, - currentPage: page, - }); - }, - }} - >
-
- - -
- ); -}; -export default ProjectDetail; diff --git a/src/router/index.tsx b/src/router/index.tsx index d7878bf0..7f03c382 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -6,7 +6,6 @@ import { Navigate, Route, Routes } from 'react-router-dom'; import { Spinner } from '@subql/components'; import { BasicRouteType, routers } from './routes'; -import { scannerRouters } from './routes'; const LazyComponent = (Component: LazyExoticComponent) => { return ( @@ -74,8 +73,4 @@ const RouterComponent: FC = () => { return {renderRoutes({ routers })}; }; -export const ScannerRouterComponent: FC = () => { - return {renderRoutes({ routers: scannerRouters })}; -}; - export default RouterComponent; diff --git a/src/router/routes.ts b/src/router/routes.ts index da686999..d3fa67a0 100644 --- a/src/router/routes.ts +++ b/src/router/routes.ts @@ -235,24 +235,3 @@ export const routers: BasicRouteType[] = [ { path: '/bridge/success/*', component: React.lazy(() => import('../pages/bridge/success/index')) }, { path: '/bridge/*', component: React.lazy(() => import('../pages/bridge/index')) }, ]; - -export const scannerRouters: BasicRouteType[] = [ - { path: '/', redirect: '/dashboard' }, - { path: '/dashboard', component: React.lazy(() => import('../pages/scanner/dashboard/index')) }, - { - path: '/project-deployment-rewards', - component: React.lazy(() => import('../pages/scanner/projectDeploymentRewards/index')), - }, - { - path: '/project-deployment-rewards/:id', - component: React.lazy(() => import('../pages/scanner/projectDetail/index')), - }, - { - path: '/node-operators', - component: React.lazy(() => import('../pages/scanner/nodeOperators/index')), - }, - { - path: '/node-operator/:id', - component: React.lazy(() => import('../pages/scanner/nodeOperatorDetail/index')), - }, -];