Skip to content

Commit

Permalink
Merge pull request #20 from TxnLab/feat/show-rewards
Browse files Browse the repository at this point in the history
Show pending rewards and bar chart of stake per pool in validator details
  • Loading branch information
pbennett authored Apr 5, 2024
2 parents 7d36b4c + 599c30d commit bf89620
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 58 deletions.
2 changes: 1 addition & 1 deletion ui/src/api/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})

Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/AddValidatorForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/ValidatorDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,10 @@ export function ValidatorDetails({ validator }: ValidatorDetailsProps) {
<div className="grid gap-4 lg:grid-cols-7">
<Card className="lg:col-span-4">
<CardHeader>
<CardTitle>Analytics</CardTitle>
<CardTitle>Stake by Pool</CardTitle>
</CardHeader>
<CardContent className="pl-2">
<Overview />
<Overview validator={validator} />
</CardContent>
</Card>
<Card className="lg:col-span-3">
Expand Down
39 changes: 39 additions & 0 deletions ui/src/components/ValidatorRewards.tsx
Original file line number Diff line number Diff line change
@@ -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 <span>Loading...</span>
}
if (totalBalancesQuery.error || totalBalancesQuery.data == undefined) {
return <span className="text-sm text-red-500">Error fetching balance</span>
}
return <AlgoDisplayAmount amount={totalBalancesQuery.data} microalgos />
}
12 changes: 12 additions & 0 deletions ui/src/components/ValidatorTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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[]
Expand Down Expand Up @@ -148,6 +149,17 @@ export function ValidatorTable({
)
},
},
{
id: 'reward',
accessorFn: (row) => row.state.totalStakers,
header: ({ column }) => <DataTableColumnHeader column={column} title="Reward Avail" />,
cell: ({ row }) => {
const validator = row.original
if (validator.state.numPools == 0) return '--'

return <ValidatorRewards validator={validator} />
},
},
{
id: 'commission',
accessorFn: (row) => row.config.percentToValidator,
Expand Down
66 changes: 13 additions & 53 deletions ui/src/components/_Overview.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<ResponsiveContainer width="100%" height={350}>
<BarChart data={data}>
<BarChart data={poolData}>
<XAxis dataKey="name" stroke="#888888" fontSize={12} tickLine={false} axisLine={false} />
<YAxis
stroke="#888888"
Expand All @@ -63,7 +23,7 @@ export function Overview() {
axisLine={false}
tickFormatter={(value) => `${value}`}
/>
<Bar dataKey="total" fill="currentColor" radius={[4, 4, 0, 0]} className="fill-primary" />
<Bar dataKey="staked" fill="currentColor" radius={[4, 4, 0, 0]} className="fill-primary" />
</BarChart>
</ResponsiveContainer>
)
Expand Down

0 comments on commit bf89620

Please sign in to comment.