diff --git a/ui/src/api/queries.ts b/ui/src/api/queries.ts index d893b9e6..679dd2a6 100644 --- a/ui/src/api/queries.ts +++ b/ui/src/api/queries.ts @@ -21,7 +21,7 @@ export const validatorQueryOptions = (validatorId: number | string) => queryOptions({ queryKey: ['validator', String(validatorId)], queryFn: () => fetchValidator(validatorId), - // staleTime: Infinity, + refetchInterval: 1000, // 1 min polling on validator info retry: false, }) diff --git a/ui/src/components/AddValidatorForm.tsx b/ui/src/components/AddValidatorForm.tsx index e4130992..bfe8ca77 100644 --- a/ui/src/components/AddValidatorForm.tsx +++ b/ui/src/components/AddValidatorForm.tsx @@ -112,7 +112,7 @@ export function AddValidatorForm({ constraints }: AddValidatorFormProps) { const debouncedCheck = useDebouncedCallback(async (value) => { const isValid = await form.trigger('nfdForInfo') if (isValid) { - fetchNfdForInfo(value) + await fetchNfdForInfo(value) } }, 500) @@ -273,7 +273,7 @@ export function AddValidatorForm({ constraints }: AddValidatorFormProps) { }, ) - navigate({ to: '/' }) + await navigate({ to: '/' }) } catch (error) { toast.error('Failed to create validator', { id: toastId }) console.error(error) diff --git a/ui/src/components/ValidatorDetails.tsx b/ui/src/components/ValidatorDetails.tsx index 3222397e..728e3807 100644 --- a/ui/src/components/ValidatorDetails.tsx +++ b/ui/src/components/ValidatorDetails.tsx @@ -109,10 +109,10 @@ export function ValidatorDetails({ validator }: ValidatorDetailsProps) {
- Analytics + Stake by Pool - + diff --git a/ui/src/components/ValidatorRewards.tsx b/ui/src/components/ValidatorRewards.tsx new file mode 100644 index 00000000..6107488b --- /dev/null +++ b/ui/src/components/ValidatorRewards.tsx @@ -0,0 +1,39 @@ +import { Validator } from '@/interfaces/validator' +import { useQuery } from '@tanstack/react-query' +import { getAccountBalance } from '@/api/algod' +import { getApplicationAddress } from 'algosdk' +import { AlgoDisplayAmount } from '@/components/AlgoDisplayAmount' + +async function fetchTotalBalances(validator: Validator) { + try { + let totalBalances = 0 + for (const pool of validator.pools) { + const poolBal = await getAccountBalance(getApplicationAddress(pool.poolAppId), true) + totalBalances += poolBal + } + return totalBalances - Number(validator.state.totalAlgoStaked) + } catch (error) { + console.error(error) + return 0 + } +} + +interface ValidatorRewardsProps { + validator: Validator +} + +export function ValidatorRewards({ validator }: ValidatorRewardsProps) { + const totalBalancesQuery = useQuery({ + queryKey: ['valrewards', validator.id], + queryFn: () => fetchTotalBalances(validator), + refetchInterval: 30000, + }) + + if (totalBalancesQuery.isLoading) { + return Loading... + } + if (totalBalancesQuery.error || totalBalancesQuery.data == undefined) { + return Error fetching balance + } + return +} diff --git a/ui/src/components/ValidatorTable.tsx b/ui/src/components/ValidatorTable.tsx index ab7c74df..27e17840 100644 --- a/ui/src/components/ValidatorTable.tsx +++ b/ui/src/components/ValidatorTable.tsx @@ -53,6 +53,7 @@ import { formatDuration } from '@/utils/dayjs' import { sendRewardTokensToPool } from '@/utils/development' import { ellipseAddress } from '@/utils/ellipseAddress' import { cn } from '@/utils/ui' +import { ValidatorRewards } from '@/components/ValidatorRewards' interface ValidatorTableProps { validators: Validator[] @@ -148,6 +149,17 @@ export function ValidatorTable({ ) }, }, + { + id: 'reward', + accessorFn: (row) => row.state.totalStakers, + header: ({ column }) => , + cell: ({ row }) => { + const validator = row.original + if (validator.state.numPools == 0) return '--' + + return + }, + }, { id: 'commission', accessorFn: (row) => row.config.percentToValidator, diff --git a/ui/src/components/_Overview.tsx b/ui/src/components/_Overview.tsx index 2d73d9de..8f57b0ec 100644 --- a/ui/src/components/_Overview.tsx +++ b/ui/src/components/_Overview.tsx @@ -1,60 +1,20 @@ import { Bar, BarChart, ResponsiveContainer, XAxis, YAxis } from 'recharts' +import { Validator } from '@/interfaces/validator' -const data = [ - { - name: 'Jan', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Feb', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Mar', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Apr', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'May', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Jun', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Jul', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Aug', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Sep', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Oct', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Nov', - total: Math.floor(Math.random() * 5000) + 1000, - }, - { - name: 'Dec', - total: Math.floor(Math.random() * 5000) + 1000, - }, -] +interface OverviewProps { + validator: Validator +} + +export function Overview({ validator }: OverviewProps) { + const poolData = validator?.pools.map((pool, index) => ({ + name: `Pool ${index + 1}`, + stakers: pool.totalStakers, + staked: Number(pool.totalAlgoStaked / BigInt(1e6)), + })) -export function Overview() { return ( - + `${value}`} /> - + )