Skip to content

Commit

Permalink
Merge pull request #15 from TxnLab/fix/ui-use-protocol-constraints
Browse files Browse the repository at this point in the history
feat(ui): prefetch protocol constraints
  • Loading branch information
pbennett authored Apr 4, 2024
2 parents f14d61d + 11e692e commit 67aa509
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 28 deletions.
15 changes: 9 additions & 6 deletions ui/src/components/StakingTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useQuery, useQueryClient } from '@tanstack/react-query'
import { useQueryClient } from '@tanstack/react-query'
import { useRouter } from '@tanstack/react-router'
import {
ColumnDef,
Expand All @@ -15,7 +15,6 @@ import { useWallet } from '@txnlab/use-wallet-react'
import dayjs from 'dayjs'
import { FlaskConical, MoreHorizontal } from 'lucide-react'
import * as React from 'react'
import { constraintsQueryOptions } from '@/api/queries'
import { AddStakeModal } from '@/components/AddStakeModal'
import { AlgoDisplayAmount } from '@/components/AlgoDisplayAmount'
import { DataTableColumnHeader } from '@/components/DataTableColumnHeader'
Expand All @@ -38,7 +37,7 @@ import {
} from '@/components/ui/table'
import { UnstakeModal } from '@/components/UnstakeModal'
import { StakerValidatorData } from '@/interfaces/staking'
import { Validator } from '@/interfaces/validator'
import { Constraints, Validator } from '@/interfaces/validator'
import { canManageValidator, isStakingDisabled, isUnstakingDisabled } from '@/utils/contracts'
import { simulateEpoch } from '@/utils/development'
import { cn } from '@/utils/ui'
Expand All @@ -47,9 +46,15 @@ interface StakingTableProps {
validators: Validator[]
stakesByValidator: StakerValidatorData[]
isLoading: boolean
constraints: Constraints
}

export function StakingTable({ validators, stakesByValidator, isLoading }: StakingTableProps) {
export function StakingTable({
validators,
stakesByValidator,
isLoading,
constraints,
}: StakingTableProps) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
Expand All @@ -60,8 +65,6 @@ export function StakingTable({ validators, stakesByValidator, isLoading }: Staki

const { transactionSigner, activeAddress } = useWallet()

const { data: constraints } = useQuery(constraintsQueryOptions)

const router = useRouter()
const queryClient = useQueryClient()

Expand Down
19 changes: 10 additions & 9 deletions ui/src/components/ValidatorTable.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { AlgoAmount } from '@algorandfoundation/algokit-utils/types/amount'
import { useQuery } from '@tanstack/react-query'
import { Link } from '@tanstack/react-router'
import {
ColumnDef,
Expand All @@ -15,7 +14,6 @@ import {
import { useWallet } from '@txnlab/use-wallet-react'
import { FlaskConical, MoreHorizontal } from 'lucide-react'
import * as React from 'react'
import { constraintsQueryOptions } from '@/api/queries'
import { AddPoolModal } from '@/components/AddPoolModal'
import { AddStakeModal } from '@/components/AddStakeModal'
import { AlgoDisplayAmount } from '@/components/AlgoDisplayAmount'
Expand All @@ -42,7 +40,7 @@ import {
} from '@/components/ui/table'
import { UnstakeModal } from '@/components/UnstakeModal'
import { StakerValidatorData } from '@/interfaces/staking'
import { Validator } from '@/interfaces/validator'
import { Constraints, Validator } from '@/interfaces/validator'
import {
calculateMaxStake,
calculateMaxStakers,
Expand All @@ -59,9 +57,14 @@ import { cn } from '@/utils/ui'
interface ValidatorTableProps {
validators: Validator[]
stakesByValidator: StakerValidatorData[]
constraints: Constraints
}

export function ValidatorTable({ validators, stakesByValidator }: ValidatorTableProps) {
export function ValidatorTable({
validators,
stakesByValidator,
constraints,
}: ValidatorTableProps) {
const [sorting, setSorting] = React.useState<SortingState>([])
const [columnFilters, setColumnFilters] = React.useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
Expand All @@ -73,8 +76,6 @@ export function ValidatorTable({ validators, stakesByValidator }: ValidatorTable

const { transactionSigner, activeAddress } = useWallet()

const { data: constraints } = useQuery(constraintsQueryOptions)

const columns: ColumnDef<Validator>[] = [
{
accessorKey: 'id',
Expand Down Expand Up @@ -138,7 +139,7 @@ export function ValidatorTable({ validators, stakesByValidator }: ValidatorTable
if (validator.state.numPools == 0) return '--'

const totalStakers = validator.state.totalStakers
const maxStakers = calculateMaxStakers(validator)
const maxStakers = calculateMaxStakers(validator, constraints)

return (
<span className="whitespace-nowrap">
Expand Down Expand Up @@ -173,7 +174,7 @@ export function ValidatorTable({ validators, stakesByValidator }: ValidatorTable
const validator = row.original
const stakingDisabled = isStakingDisabled(activeAddress, validator, constraints)
const unstakingDisabled = isUnstakingDisabled(activeAddress, validator, stakesByValidator)
const addingPoolDisabled = isAddingPoolDisabled(activeAddress, validator)
const addingPoolDisabled = isAddingPoolDisabled(activeAddress, validator, constraints)
const canManage = canManageValidator(activeAddress, validator)

const isDevelopment = process.env.NODE_ENV === 'development'
Expand Down Expand Up @@ -313,7 +314,7 @@ export function ValidatorTable({ validators, stakesByValidator }: ValidatorTable
))}
</TableHeader>
<TableBody>
{table.getRowModel().rows?.length ? (
{table.getRowModel().rows.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} data-state={row.getIsSelected() && 'selected'}>
{row.getVisibleCells().map((cell) => (
Expand Down
23 changes: 20 additions & 3 deletions ui/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useQuery, useSuspenseQuery } from '@tanstack/react-query'
import { createFileRoute } from '@tanstack/react-router'
import { useWallet } from '@txnlab/use-wallet-react'
import { fetchStakerValidatorData } from '@/api/contracts'
import { validatorsQueryOptions } from '@/api/queries'
import { constraintsQueryOptions, validatorsQueryOptions } from '@/api/queries'
import { Meta } from '@/components/Meta'
import { PageHeader } from '@/components/PageHeader'
import { PageMain } from '@/components/PageMain'
Expand All @@ -11,7 +11,16 @@ import { ValidatorTable } from '@/components/ValidatorTable'
import { StakerValidatorData } from '@/interfaces/staking'

export const Route = createFileRoute('/')({
loader: ({ context: { queryClient } }) => queryClient.ensureQueryData(validatorsQueryOptions),
beforeLoad: () => {
return {
validatorsQueryOptions,
constraintsQueryOptions,
}
},
loader: async ({ context: { queryClient, validatorsQueryOptions, constraintsQueryOptions } }) => {
queryClient.ensureQueryData(validatorsQueryOptions)
queryClient.ensureQueryData(constraintsQueryOptions)
},
component: Dashboard,
pendingComponent: () => <div>Loading...</div>,
errorComponent: ({ error }) => {
Expand All @@ -26,6 +35,9 @@ function Dashboard() {
const validatorsQuery = useSuspenseQuery(validatorsQueryOptions)
const validators = validatorsQuery.data

const constraintsQuery = useSuspenseQuery(constraintsQueryOptions)
const constraints = constraintsQuery.data

const { activeAddress } = useWallet()

const stakesQuery = useQuery<StakerValidatorData[]>({
Expand All @@ -47,8 +59,13 @@ function Dashboard() {
validators={validators || []}
stakesByValidator={stakesByValidator}
isLoading={stakesQuery.isLoading}
constraints={constraints}
/>
<ValidatorTable
validators={validators || []}
stakesByValidator={stakesByValidator}
constraints={constraints}
/>
<ValidatorTable validators={validators || []} stakesByValidator={stakesByValidator} />
</div>
</PageMain>
</>
Expand Down
21 changes: 11 additions & 10 deletions ui/src/utils/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -405,9 +405,8 @@ export function calculateMaxStake(
return maxStake
}

export function calculateMaxStakers(validator: Validator): number {
// @todo: fetch max stakers from contract
const maxStakersPerPool = 200
export function calculateMaxStakers(validator: Validator, constraints?: Constraints): number {
const maxStakersPerPool = constraints?.maxStakersPerPool || 0
const maxStakers = maxStakersPerPool * validator.state.numPools

return maxStakers
Expand All @@ -428,8 +427,7 @@ export function isStakingDisabled(
maxAlgoPerPool = constraints.maxAlgoPerPool
}

// @todo: fetch max stakers from contract
const maxStakersPerPool = 200
const maxStakersPerPool = constraints?.maxStakersPerPool || 0

const maxStakers = maxStakersPerPool * numPools
const maxStake = Number(maxAlgoPerPool) * numPools
Expand All @@ -455,16 +453,19 @@ export function isUnstakingDisabled(
return noPools || !validatorHasStake
}

export function isAddingPoolDisabled(activeAddress: string | null, validator: Validator): boolean {
if (!activeAddress) {
export function isAddingPoolDisabled(
activeAddress: string | null,
validator: Validator,
constraints?: Constraints,
): boolean {
if (!activeAddress || !constraints) {
return true
}
// @todo: define totalNodes as global constant or fetch from protocol constraints
const totalNodes = 4
const maxNodes = constraints.maxNodes
const { numPools } = validator.state
const { poolsPerNode } = validator.config

const hasAvailableSlots = numPools < poolsPerNode * totalNodes
const hasAvailableSlots = numPools < poolsPerNode * maxNodes

return !hasAvailableSlots
}
Expand Down

0 comments on commit 67aa509

Please sign in to comment.