Skip to content

Commit

Permalink
back to state
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar committed Nov 21, 2024
1 parent 8768edd commit 47115cd
Show file tree
Hide file tree
Showing 25 changed files with 678 additions and 544 deletions.
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 = newTotalAllocation / BigInt(allocationCount)

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
@@ -1,13 +1,9 @@
'use client'

import { formatBalanceToHuman, getTokenBalance } from '@/app/user/Balances/balanceUtils'
import { useGetAddressTokens } from '@/app/user/Balances/hooks/useGetAddressTokens'
import { withSpinner } from '@/components/LoadingSpinner/withLoadingSpinner'
import { Paragraph } from '@/components/Typography'
import { ethers } from 'ethers'
import { useAccount } from 'wagmi'
import { useHandleErrors } from '../../utils'
import { useBackerTotalAllocation } from '../hooks/useBackerTotalAllocation'
import { useContext } from 'react'
import { formatEther } from 'viem'
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'

type ValueProps = {
value: string
Expand All @@ -33,60 +29,39 @@ const Column = ({ children }: { children: React.ReactNode }) => {
const Balance = ({ value }: ValueProps) => {
return <Metric name="Balance" value={value} />
}
const BalanceWithSpinner = withSpinner(Balance)

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

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

export const AllocationMetrics = () => {
// TODO: we can move this logic to a custom hook or to a context
const { address, chainId } = useAccount()
let {
data,
isLoading: balanceLoading,
error: balanceError,
} = useGetAddressTokens(address!, chainId as number)
const stRIFBalance = getTokenBalance('stRIF', data)
const balanceValue = `${stRIFBalance.balance} ${stRIFBalance.symbol}`
balanceLoading = false
const {
initialState: {
backer: { totalAllocation, balance },
},
} = useContext(AllocationsContext)

let {
data: allocatedAmount,
isLoading: allocatedAmountLoading,
error: allocatedAmountError,
} = useBackerTotalAllocation(address!)
const allocatedAmountValue = `${allocatedAmount} ${stRIFBalance.symbol}`
allocatedAmountLoading = false
allocatedAmount = 0n
const balanceValue = `${formatEther(balance)} stRIF`

useHandleErrors({
error: balanceError ?? allocatedAmountError,
title: 'Failed to fetch balance and allocated amount',
})
const allocatedAmountValue = `${formatEther(totalAllocation)} stRIF`

const unformattedUnit = stRIFBalance.balance
const formattedUnit = ethers.parseEther(unformattedUnit)
const unallocatedAmount = formatBalanceToHuman(formattedUnit - (allocatedAmount || 0n))
const unallocatedAmount = formatEther(balance - totalAllocation)

const unallocatedAmountValue = `${unallocatedAmount} ${stRIFBalance.symbol}`
const unallocatedAmountLoading = balanceLoading || allocatedAmountLoading
const unallocatedAmountValue = `${unallocatedAmount} stRIF`
return (
<div className="flex items-start gap-6 w-full">
<Column>
<BalanceWithSpinner value={balanceValue} isLoading={balanceLoading} />
<Balance value={balanceValue} />
</Column>
<Column>
<AllocatedAmountWithSpinner value={allocatedAmountValue} isLoading={allocatedAmountLoading} />
<AllocatedAmount value={allocatedAmountValue} />
</Column>
<Column>
<UnallocatedAmountWithSpinner value={unallocatedAmountValue} isLoading={unallocatedAmountLoading} />
<UnallocatedAmount value={unallocatedAmountValue} />
</Column>
</div>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,43 @@
import { formatBalanceToHuman } from '@/app/user/Balances/balanceUtils'
import { Input } from '@/components/Input'
import { Slider } from '@/components/Slider'
import { Label } from '@/components/Typography'
import { useState } from 'react'
import { useContext } from 'react'
import { formatEther, parseEther } from 'viem'
import { AllocationsContext } from '@/app/collective-rewards/allocations/context'
import { BuilderAllocationHeader, BuilderAllocationHeaderProps } from './BuilderAllocationHeader'
import { Address } from 'viem'
import { BuilderStatusShown } from '../../types'
import { BuilderInfo } from '@/app/collective-rewards/types'

export type BuilderStatus = BuilderStatusShown | 'Paused' | 'Deactivated'

export type BuilderAllocationProps = BuilderAllocationHeaderProps & {
allocationLeft: BigInt
// TODO: what's the value we expect here? (e.g. 8% or 8.123456%)
backerRewards: number
currentAllocation: number
}
export type BuilderAllocationProps = BuilderAllocationHeaderProps &
Pick<BuilderInfo, 'kickback'> & {
index: number
currentAllocation: bigint
}

export const BuilderAllocation = (builder: BuilderAllocationProps) => {
const [sliderValue, setSliderValue] = useState<number>(builder.currentAllocation)
/* TODO: when the cumulative amount exceeds the balance
* - hint is changed
* - Slider is hidden
*/
const hint = `Allocation left ${formatBalanceToHuman(builder.allocationLeft.toString())} stRIF`
// const hint = <StakeHint />
const onInputChange = () => {
/* TODO:
* - reset all the sliders to 0 when the user changes the input
* - update the cumulative amount
* - if the cumulative amount exceeds the total allocation, show an error message in the current input
*/
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))
}

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)]">
<BuilderAllocationHeader {...builder} />
<Label className="font-bold">Backer rewards {builder.backerRewards}% </Label>
<Input type="number" name={`allocation-${builder.address}`} hint={hint} onChange={onInputChange} />
<Slider value={[sliderValue]} />
<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) / Number(totalAllocation)) * 100]} />
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ import { AddressOrAlias } from '@/components/Address'
import { Badge } from '@/components/Badge'
import { Jdenticon } from '@/components/Header/Jdenticon'
import { Paragraph, Typography } from '@/components/Typography'
import { BuilderStatusActive, BuilderStatusShown } from '../../types'
import { crStatusColorClasses } from '../../user'
import {
BuilderInfo,
BuilderStatus,
BuilderStatusActive,
BuilderStatusShown,
} from '@/app/collective-rewards/types'
import { crStatusColorClasses } from '@/app/collective-rewards/user'
import { Address } from 'viem'
import { FC } from 'react'

export type BuilderAllocationHeaderProps = {
address: Address
builderName: string
status: BuilderStatusShown
joiningDate: string
}
export type BuilderAllocationHeaderProps = Pick<
BuilderInfo,
'address' | 'builderName' | 'status' | 'joiningDate'
>

export const BuilderAllocationHeader: FC<BuilderAllocationHeaderProps> = ({
address,
Expand All @@ -28,7 +31,10 @@ export const BuilderAllocationHeader: FC<BuilderAllocationHeaderProps> = ({
<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'
43 changes: 0 additions & 43 deletions src/app/collective-rewards/allocations/context/Action.d.ts

This file was deleted.

Loading

0 comments on commit 47115cd

Please sign in to comment.