Skip to content

Commit

Permalink
feat(cr): add allocation context (#374)
Browse files Browse the repository at this point in the history
back to state

pagination and safer context return

chore: review allocations

fix: make builder context global
  • Loading branch information
jurajpiar authored Nov 21, 2024
1 parent 3c16696 commit 5cc1729
Show file tree
Hide file tree
Showing 34 changed files with 769 additions and 278 deletions.
3 changes: 3 additions & 0 deletions .env.testnet.local
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ NEXT_PUBLIC_GENERAL_BUCKET_ADDRESS=0x72Ed7d7b7835Ad62B1f9b6280bAd62618aA71461
NEXT_PUBLIC_CHAIN_ID=31

# CR-related env variables
# TODO: To be removed
NEXT_PUBLIC_SIMPLIFIED_REWARD_DISTRIBUTOR_ADDRESS=0xc469Cc2579De5C16210e9063B4E628bF8C46bA02

NEXT_PUBLIC_BACKERS_MANAGER_ADDRESS=0xec0a29Df5180A6B04496dfAf2D827e36F4a0A52F
NEXT_PUBLIC_REWARD_DISTRIBUTOR_ADDRESS=0xD476E4804551595687C1f6F0a9C22dd1Bbfa0319
NEXT_PUBLIC_GOVERNANCE_MANAGER_ADDRESS=0xb7C6918d6aE6df2e147FF464271a94EAfF027E5D
Expand Down
93 changes: 0 additions & 93 deletions src/app/collective-rewards/allocations/AllocationMetrics.tsx

This file was deleted.

32 changes: 0 additions & 32 deletions src/app/collective-rewards/allocations/BuilderAllocation.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
'use client'

import { formatBalanceToHuman } from '@/app/user/Balances/balanceUtils'
import { Button, ButtonProps } from '@/components/Button'
import { Input } from '@/components/Input'
import { cn } from '@/lib/utils'
import { useState } from 'react'
import { useContext, useState } from 'react'
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'
import { formatEther, parseEther } from 'viem'
import { StakeHint } from './StakeHint'

const PercentageButton = ({ children, variant, ...rest }: ButtonProps) => (
<Button
Expand All @@ -16,29 +18,30 @@ const PercentageButton = ({ children, variant, ...rest }: ButtonProps) => (
</Button>
)

type AllocationAmountProps = {
balance: bigint
errorMessage?: string
onPercentageSet?: (percentage: number) => void
}
const ALLOCATION_EXCEED_AMOUNT_ERROR = 'Builder allocations exceeds amount to allocate'

export const AllocationAmount = ({ balance, errorMessage, onPercentageSet }: AllocationAmountProps) => {
// TODO: hint is shown only when the allocated amount exceeds the balance
// const hint = <StakeHint />
const hint = undefined
export const AllocationAmount = () => {
const {
state: {
backer: { balance, totalAllocation, cumulativeAllocation, allocationCount },
},
actions: { updateAllocations, updateTotalAllocation },
} = useContext(AllocationsContext)

const [activeButton, setActiveButton] = useState<number | null>(null)
const [allocatedAmount, setAllocatedAmount] = useState('0')
const onChange = (value: string) => {
setAllocatedAmount(value)
}

const onPercentageButtonClicked = (percentage: number, index: number) => {
const percentageAmount = (BigInt(balance ?? 0n) * BigInt(percentage)) / BigInt(100)
setAllocatedAmount(formatBalanceToHuman(percentageAmount))
onPercentageSet?.(percentage)
const newTotalAllocation = (BigInt(balance ?? 0n) * BigInt(percentage)) / BigInt(100)
updateTotalAllocation(newTotalAllocation)
setActiveButton(index)
const allocationValue = allocationCount > 0 ? newTotalAllocation / BigInt(allocationCount) : 0n

updateAllocations(Array(allocationCount).fill(allocationValue))
}

const handleOnChange = (value: string) => {
updateTotalAllocation(parseEther(value))
}

return (
<div className="flex flex-col items-end gap-4 min-w-[694px] min-h-[130px]">
<div className="flex flex-col items-center gap-[10px] self-stretch">
Expand All @@ -49,10 +52,14 @@ export const AllocationAmount = ({ balance, errorMessage, onPercentageSet }: All
labelProps={{ className: 'text-base leading-4 font-normal' }}
name="allocated-amount"
fullWidth
onChange={onChange}
value={allocatedAmount.toString()}
errorMessage={errorMessage}
hint={hint}
onChange={handleOnChange}
value={formatEther(totalAllocation)}
errorMessage={
cumulativeAllocation > totalAllocation && cumulativeAllocation < balance
? ALLOCATION_EXCEED_AMOUNT_ERROR
: ''
}
hint={Number(totalAllocation - cumulativeAllocation) < 0 ? <StakeHint /> : undefined}
/>
</div>
<div className="flex items-center gap-3">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
'use client'

import { Paragraph } from '@/components/Typography'
import { useContext } from 'react'
import { formatEther } from 'viem'
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'

type ValueProps = {
value: string
}

type MetricsProps = ValueProps & {
name: string
}

const Metric = ({ name, value }: MetricsProps) => {
return (
<div className="flex flex-col items-start gap-[10px]">
<Paragraph className="font-bold tracking-[-0.28px] text-[14px]">{name}</Paragraph>
<Paragraph className="font-kk-topo text-[48px] text-primary">{value}</Paragraph>
</div>
)
}

const Column = ({ children }: { children: React.ReactNode }) => {
return <div className="flex flex-col items-start gap-[10px] min-w-[200px] max-w-[20%]">{children}</div>
}

const Balance = ({ value }: ValueProps) => {
return <Metric name="Balance" value={value} />
}

const AllocatedAmount = ({ value }: ValueProps) => {
return <Metric name="Allocated amount" value={value} />
}

const UnallocatedAmount = ({ value }: ValueProps) => {
return <Metric name="Unallocated amount" value={value} />
}

export const AllocationMetrics = () => {
const {
initialState: {
backer: { totalAllocation, balance },
},
} = useContext(AllocationsContext)

const balanceValue = `${formatEther(balance)} stRIF`

const allocatedAmountValue = `${formatEther(totalAllocation)} stRIF`

const unallocatedAmount = formatEther(balance - totalAllocation)

const unallocatedAmountValue = `${unallocatedAmount} stRIF`
return (
<div className="flex items-start gap-6 w-full">
<Column>
<Balance value={balanceValue} />
</Column>
<Column>
<AllocatedAmount value={allocatedAmountValue} />
</Column>
<Column>
<UnallocatedAmount value={unallocatedAmountValue} />
</Column>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'
import { Builder } from '@/app/collective-rewards/types'
import { Input } from '@/components/Input'
import { Slider } from '@/components/Slider'
import { Label } from '@/components/Typography'
import { useContext } from 'react'
import { formatEther, parseEther } from 'viem'
import { BuilderAllocationHeader, BuilderAllocationHeaderProps } from './BuilderAllocationHeader'

export type BuilderAllocationProps = BuilderAllocationHeaderProps &
Pick<Builder, 'kickback'> & {
index: number
currentAllocation: bigint
}

export const BuilderAllocation = (builder: BuilderAllocationProps) => {
const {
state: {
backer: { totalAllocation, cumulativeAllocation },
},
actions: { updateAllocation },
} = useContext(AllocationsContext)
const allocationLeft = totalAllocation - cumulativeAllocation
const { currentAllocation, kickback, address } = builder
const onInputChange = (value: string) => {
updateAllocation(builder.index, parseEther(value))
}

const onSliderValueChange = (value: number[]) => {
updateAllocation(builder.index, BigInt(value[0]))
}

return (
<div className="flex flex-col py-4 px-2 gap-6 shrink-0 bg-foreground min-w-[calc(25%-1rem)] max-w-[calc(25%-1rem)] rounded-[8px]">
<BuilderAllocationHeader {...builder} />
<Label className="font-bold">Backer rewards {kickback}% </Label>
<Input
type="number"
name={`allocation-${address}`}
hint={`Allocation left ${allocationLeft > 0 ? formatEther(allocationLeft) : '0'} stRIF`}
onChange={onInputChange}
value={formatEther(currentAllocation)}
/>
<Slider
value={[Number(currentAllocation)]}
max={Number(totalAllocation)}
onValueChange={onSliderValueChange}
/>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
import { Builder, BuilderStatusActive, BuilderStatusShown } from '@/app/collective-rewards/types'
import { crStatusColorClasses } from '@/app/collective-rewards/user'
import { AddressOrAlias } from '@/components/Address'
import { Badge } from '@/components/Badge'
import { Jdenticon } from '@/components/Header/Jdenticon'
import { Paragraph, Typography } from '@/components/Typography'
import { BuilderStatusActive } from '../types'
import { crStatusColorClasses } from '../user'
import { BuilderAllocationProps } from './types'
import { FC } from 'react'

export const BuilderAllocationHeader = ({
export type BuilderAllocationHeaderProps = Pick<Builder, 'address' | 'builderName' | 'status' | 'joiningDate'>

export const BuilderAllocationHeader: FC<BuilderAllocationHeaderProps> = ({
address,
builderName,
status,
joiningDate,
}: BuilderAllocationProps) => {
}) => {
return (
<div className="flex flex-row w-full items-center content-between gap-3">
<Jdenticon className="rounded-md bg-white" value={address} size="46" />
Expand All @@ -20,7 +22,10 @@ export const BuilderAllocationHeader = ({
<AddressOrAlias addressOrAlias={builderName || address} className="text-base font-bold leading-4" />
</Typography>
{status !== BuilderStatusActive && (
<Badge content={status} className={`${crStatusColorClasses[status]} py-1 px-1 text-[12px]`} />
<Badge
content={status}
className={`${crStatusColorClasses[status as BuilderStatusShown]} py-1 px-1 text-[12px]`}
/>
)}
{status === BuilderStatusActive && (
<Paragraph className="text-sm font-light"> Joined {joiningDate}</Paragraph>
Expand Down
5 changes: 5 additions & 0 deletions src/app/collective-rewards/allocations/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './AllocationAmount'
export * from './AllocationMetrics'
export * from './BuilderAllocation'
export * from './Header'
export * from './StakeHint'
Loading

0 comments on commit 5cc1729

Please sign in to comment.