Skip to content

Commit

Permalink
TOK-515: include halted builders (#430)
Browse files Browse the repository at this point in the history
* refactor: get all builders

* refactor: include halted gauges

* refactor: pr comments

* chore: prettier
  • Loading branch information
franciscotobar authored Dec 4, 2024
1 parent beaa8e7 commit b4845d8
Show file tree
Hide file tree
Showing 10 changed files with 102 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@ import { Badge } from '@/components/Badge'
import { Jdenticon } from '@/components/Header/Jdenticon'
import { Paragraph, Typography } from '@/components/Typography'
import { FC } from 'react'
import { Builder, BuilderProposal, BuilderStateFlags } from '../../types'
import { Builder, BuilderProposal, BuilderStateFlags } from '@/app/collective-rewards/types'
import { getBuilderInactiveState } from '@/app/collective-rewards/utils'

export type BuilderAllocationHeaderProps = Pick<Builder, 'builderName' | 'address' | 'stateFlags' | 'gauge'> &
Pick<BuilderProposal, 'date'>

const isBuilderActive = ({ communityApproved, kycApproved, paused }: BuilderStateFlags) => {
return communityApproved && kycApproved && !paused
const isBuilderActive = ({ communityApproved, kycApproved, paused, revoked }: BuilderStateFlags) => {
return communityApproved && kycApproved && !paused && !revoked
}

const haltedClass = 'bg-[#932309] color-text-primary py-1 px-1 text-[12px]'
const haltedStateBadges = {
Paused: <Badge content="Paused" className="bg-[#F9E1FF] text-secondary py-1 px-1 text-[12px]" />,
Deactivated: <Badge content="Deactivated" className={haltedClass} />,
KYCRevoked: <Badge content="KYC Revoked" className={haltedClass} />,
Revoked: <Badge content="Revoked" className={haltedClass} />,
}

export const BuilderAllocationHeader: FC<BuilderAllocationHeaderProps> = ({
Expand All @@ -28,13 +37,11 @@ export const BuilderAllocationHeader: FC<BuilderAllocationHeaderProps> = ({
<Typography tagVariant="label" className="font-semibold line-clamp-1 text-wrap text-base leading-4">
<AddressOrAlias addressOrAlias={builderName || address} className="text-base font-bold leading-4" />
</Typography>
{gauge && !state.communityApproved && (
<Badge content="Deactivated" className="bg-[#932309] color-text-primary py-1 px-1 text-[12px]" />
)}
{state.paused && state.communityApproved && (
<Badge content="Paused" className="bg-[#F9E1FF] text-secondary py-1 px-1 text-[12px]" />
{gauge && isBuilderActive(state) ? (
<Paragraph className="text-sm font-light"> Joined {date}</Paragraph>
) : (
haltedStateBadges[getBuilderInactiveState(state)]
)}
{isBuilderActive(state) && <Paragraph className="text-sm font-light"> Joined {date}</Paragraph>}
</div>
</div>
)
Expand Down
4 changes: 2 additions & 2 deletions src/app/collective-rewards/metrics/Metrics.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useGetGaugesArray, withBuilderButton } from '@/app/collective-rewards/user'
import { useGetGaugesArrayByType, withBuilderButton } from '@/app/collective-rewards/user'
import { HeaderTitle } from '@/components/Typography'
import {
TotalAllocationsMetrics,
Expand All @@ -15,7 +15,7 @@ import { PricesContextProvider } from '@/shared/context/PricesContext'
const HeaderWithBuilderButton = withBuilderButton(HeaderTitle)

export const Metrics = () => {
const { data: activeGauges } = useGetGaugesArray('active')
const { data: activeGauges } = useGetGaugesArrayByType('active')
const gauges = activeGauges ?? []

const tokens = {
Expand Down
8 changes: 3 additions & 5 deletions src/app/collective-rewards/rewards/MyRewards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,17 @@ const SubText = () => {

export const Rewards: FC<{ builder: Address }> = ({ builder }) => {
const router = useRouter()
const { data: rewardGauges, error: rewardGaugesError } = useGetGaugesArray('active')
const { data: haltedGauges, error: haltedGaugesError } = useGetGaugesArray('halted')
const { data: gauges, error: gaugesError } = useGetGaugesArray()
const { data: gauge, error: gaugeError } = useGetBuilderToGauge(builder)
const gauges = [...(rewardGauges ?? []), ...(haltedGauges ?? [])]

const error = rewardGaugesError ?? haltedGaugesError ?? gaugeError
const error = gaugesError ?? gaugeError

useHandleErrors({ error, title: 'Error loading gauge(s)' })

// TODO: check where to store this information
const data: RewardDetails = {
builder,
gauges,
gauges: gauges || [],
tokens: {
rif: {
address: getAddress(tokenContracts.RIF),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ type RequiredBuilder = Required<Builder>

// from the builders list, filter out the builders that are not kycApproved or are revoked or have no allocation
const isBuilderShown = (
{ stateFlags: { kycApproved, revoked }, address }: RequiredBuilder,
{ stateFlags: { kycApproved, revoked, communityApproved }, address }: RequiredBuilder,
allocations: Allocations,
) => {
const allocation = allocations[address]
return (kycApproved && !revoked) || (allocation && allocation > 0n)
return (kycApproved && !revoked && communityApproved) || (allocation && allocation > 0n)
}

// FIXME: remove and use Builder and/or combination of existing types
Expand Down
17 changes: 11 additions & 6 deletions src/app/collective-rewards/shared/components/Table/TableCells.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { ProgressBar } from '@/components/ProgressBar'
import { Button } from '@/components/Button'
import { BuilderStateFlags } from '@/app/collective-rewards/types'
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'
import { getBuilderInactiveState, isBuilderOperational } from '@/app/collective-rewards/utils'

export function getFormattedCurrency(value: number, symbol: string) {
const formattedCurrency = formatCurrency(value, symbol)
Expand Down Expand Up @@ -54,17 +55,21 @@ export const LazyRewardCell = memo(RewardCell, ({ rewards: prevReward }, { rewar
type BuilderStatusFlagProps = {
stateFlags: BuilderStateFlags
}

const getStatusColor = (isOperational: boolean, builderInactiveState: string) => {
if (isOperational) return 'transparent'
if (builderInactiveState === 'Paused') return '#F9E1FF'
return '#932309'
}
const BuilderStatusFlag: FC<BuilderStatusFlagProps> = ({ stateFlags }) => {
const isDeactivated = !stateFlags.kycApproved || !stateFlags.communityApproved
const isPaused = stateFlags.paused
const isOperational = isBuilderOperational(stateFlags)
const builderInactiveState = getBuilderInactiveState(stateFlags)

const color = isDeactivated ? '#932309' : isPaused ? '#F9E1FF' : 'transparent'
const content = isDeactivated ? 'Status: Deactivated' : isPaused ? 'Status: Paused' : ''
const color = getStatusColor(isOperational, builderInactiveState)
const content = builderInactiveState

return (
<Popover
disabled={!isDeactivated && !isPaused}
disabled={isOperational}
content={content}
className="font-normal text-sm flex items-center"
size="small"
Expand Down
2 changes: 1 addition & 1 deletion src/app/collective-rewards/user/hooks/useGetBuilders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const useGetBuilders: UseGetBuilders = () => {
* ignore the builder if paused or revoked (to be confirmed)
*/
// get the gauges
const { data: gauges, isLoading: gaugesLoading, error: gaugesError } = useGetGaugesArray('active')
const { data: gauges, isLoading: gaugesLoading, error: gaugesError } = useGetGaugesArray()

// get the builders for each gauge
const gaugeToBuilderCalls = gauges?.map(
Expand Down
70 changes: 52 additions & 18 deletions src/app/collective-rewards/user/hooks/useGetGaugesArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,11 @@ const gaugeType: Record<GaugeType, FunctionName> = {
halted: 'getHaltedGaugeAt',
}

export const useGetGaugesArray = (type: GaugeType) => {
const {
data: gaugesLength,
isLoading: gaugesLengthLoading,
error: gaugesLengthError,
} = useGetGaugesLength(type)
export const useGetGaugesArray = () => {
const { data: activeCalls, isLoading: isLoadingActive, error: errorActive } = useGetContractCalls('active')
const { data: haltedCalls, isLoading: isLoadingHalted, error: errorHalted } = useGetContractCalls('halted')

const length = Number(gaugesLength) ?? 0

const contractCalls = Array.from({ length }, (_, index) => {
return {
address: BackersManagerAddress,
abi: BuilderRegistryAbi,
functionName: gaugeType[type],
args: [index],
} as const
})
const contractCalls = [...activeCalls, ...haltedCalls]

const {
data: gaugesAddress,
Expand All @@ -47,12 +35,58 @@ export const useGetGaugesArray = (type: GaugeType) => {
})

const gauges = useMemo(() => gaugesAddress?.map(gauge => gauge.result as Address), [gaugesAddress])
const isLoading = gaugesLengthLoading || gaugesAddressLoading
const error = gaugesLengthError ?? gaugesAddressError
const isLoading = isLoadingActive || isLoadingHalted || gaugesAddressLoading
const error = errorActive ?? errorHalted ?? gaugesAddressError

return {
data: gauges,
isLoading,
error,
}
}

export const useGetGaugesArrayByType = (type: GaugeType) => {
const {
data: calls,
isLoading: contractCallsLoading,
error: contractCallsError,
} = useGetContractCalls(type)

const {
data: gaugesAddress,
isLoading: gaugesAddressLoading,
error: gaugesAddressError,
} = useReadContracts<Address[]>({
contracts: calls,
query: {
refetchInterval: AVERAGE_BLOCKTIME,
},
})

const gauges = useMemo(() => gaugesAddress?.map(gauge => gauge.result as Address), [gaugesAddress])
const isLoading = contractCallsLoading || gaugesAddressLoading
const error = contractCallsError ?? gaugesAddressError

return {
data: gauges,
isLoading: isLoading || gaugesAddressLoading,
error: error ?? gaugesAddressError,
}
}

const useGetContractCalls = (type: GaugeType) => {
const { data: gaugesLength, isLoading, error } = useGetGaugesLength(type)

const length = Number(gaugesLength) ?? 0

const data = Array.from({ length }, (_, index) => {
return {
address: BackersManagerAddress,
abi: BuilderRegistryAbi,
functionName: gaugeType[type],
args: [index],
} as const
})

return { data, isLoading, error }
}
1 change: 1 addition & 0 deletions src/app/collective-rewards/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './getCoinbaseAddress'
export * from './getMostAdvancedProposal'
export * from './handleErrors'
export * from './removeBrackets'
export * from './isBuilderOperational'
7 changes: 0 additions & 7 deletions src/app/collective-rewards/utils/isBuilderActive.ts

This file was deleted.

14 changes: 14 additions & 0 deletions src/app/collective-rewards/utils/isBuilderOperational.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { BuilderStateFlags } from '../types'

export const isBuilderOperational = (stateFlags?: BuilderStateFlags) => {
return !!(stateFlags && stateFlags.communityApproved && stateFlags.kycApproved && !stateFlags.paused)
}

const inactiveStates = ['Deactivated', 'KYCRevoked', 'Revoked', 'Paused'] as const
type InactiveState = (typeof inactiveStates)[number]
export const getBuilderInactiveState = (state: BuilderStateFlags): InactiveState => {
if (!state.communityApproved) return 'Deactivated'
if (!state.kycApproved) return 'KYCRevoked'
if (state.revoked) return 'Revoked'
return 'Paused'
}

0 comments on commit b4845d8

Please sign in to comment.