Skip to content

Commit

Permalink
feat(cr): add allocation context
Browse files Browse the repository at this point in the history
  • Loading branch information
jurajpiar committed Nov 19, 2024
1 parent f428494 commit aebbe2c
Show file tree
Hide file tree
Showing 24 changed files with 377 additions and 51 deletions.
6 changes: 3 additions & 3 deletions .env.testnet.local
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ NEXT_PUBLIC_CHAIN_ID=31

# CR-related env variables
NEXT_PUBLIC_SIMPLIFIED_REWARD_DISTRIBUTOR_ADDRESS=0x4e84FCc953dE129C6C47c5B0AD7E57B226093Ae1
NEXT_PUBLIC_BACKERS_MANAGER_ADDRESS=0xC2857F402096BfF24E8E05C2E047F8461d1af927
NEXT_PUBLIC_REWARD_DISTRIBUTOR_ADDRESS=0x21534EaE65041b85cA309C3258E967f305917F8F
NEXT_PUBLIC_GOVERNANCE_MANAGER_ADDRESS=0xAEdD29bebb0dd8e29702DD1e32346365F96aA016
NEXT_PUBLIC_BACKERS_MANAGER_ADDRESS=0x6E587f9DdEB9640713a0D735A78ac36cA4a763ea
NEXT_PUBLIC_REWARD_DISTRIBUTOR_ADDRESS=0x6F6Be08782bc671041cF240f84a5Ca671774BECc
NEXT_PUBLIC_GOVERNANCE_MANAGER_ADDRESS=0x732C2468163F16Dfc109bb68a5F87CC04bC729EF

NEXT_PUBLIC_CYCLE_DURATION_IN_DAYS=2
NEXT_PUBLIC_FIRST_CYCLE_START_DATE_ISO="1970-01-01T00:00:00Z"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ 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 './useBackerTotalAllocation'
import { useHandleErrors } from '../../utils'
import { useBackerTotalAllocation } from '../useBackerTotalAllocation'

type ValueProps = {
value: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Slider } from '@/components/Slider'
import { Label } from '@/components/Typography'
import { useState } from 'react'
import { BuilderAllocationHeader } from './BuilderAllocationHeader'
import { BuilderAllocationProps } from './types'
import { BuilderAllocationProps } from '../types'

export const BuilderAllocation = (builder: BuilderAllocationProps) => {
const [sliderValue, setSliderValue] = useState<number>(builder.currentAllocation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ 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 { BuilderStatusActive } from '../../types'
import { crStatusColorClasses } from '../../user'
import { BuilderAllocationProps } from '../types'

export const BuilderAllocationHeader = ({
address,
Expand Down
165 changes: 165 additions & 0 deletions src/app/collective-rewards/allocations/context/AllocationsContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { createContext, FC, ReactNode, useContext, useEffect, useMemo, useState } from 'react'
import { Address } from 'viem'
import { useAccount } from 'wagmi'
import { BuilderProposal, useGetActiveBuilders, useGetBuilders } from '@/app/collective-rewards/user'
import { readContract } from 'wagmi/actions'
import { config } from '@/config'
import { BackersManagerAddress } from '@/lib/contracts'
import { BuilderRegistryAbi } from '@/lib/abis/v2/BuilderRegistryAbi'
import { GaugeAbi } from '@/lib/abis/v2/GaugeAbi'
import { BuilderStateStruct } from '@/app/collective-rewards/utils/getBuilderGauge'
import { useGetAllAllocationOf } from '@/app/collective-rewards/allocations/hooks'
import { withPagination } from '@/app/collective-rewards/context/PaginatedDataContext'

type AllocationsContextValue = {
// buildersByAddress: Record<Address, BuilderInfo>
// isLoading: boolean
// user: {
// address: Address
// backees: Address[]
// isBacker: boolean
// }
// actions: {
// updateBacking: (address: Address, value: bigint) => unknown
// }
}

export const AllocationsContext = createContext<AllocationsContextValue | null>(null)

export const useAllocationsContext = () => {
const context = useContext(AllocationsContext)
if (!context) {
throw new Error('useAllocationsContext must be used within a AllocationsContextProvider')
}
return context
}

type SelectedBuilder = {
index: number
hasAllocationsByUser: boolean
isSelected: boolean
// allocate: (value: bigint) => void
}

type BuildersByAddress = Record<Address, SelectedBuilder>

export const AllocationsContextProvider: FC<{ children: ReactNode }> = ({ children }) => {
const { address: backerAddress } = useAccount()
if (!backerAddress) {
throw new Error('Provider must be used with a defined account')
}
const {
data: activeBuilders,
isLoading: isLoadingActiveBuilders,
error: activeBuildersError,
} = useGetActiveBuilders()

const [selectedBuilders, setSelectedBuilders] = useState<BuildersByAddress>({})

const {
data: onchianAllocations,
isLoading: isOnchianAllocationsLoading,
error: OnchianAllocationsError,
} = useGetAllAllocationOf(
backerAddress!,
Object.values(selectedBuilders).map(builder => activeBuilders[builder.index].gauge),
)

// useEffect(() => {
// if (!backer) {return}

// const getBuilderGauge = async (builderAddress: Address): Promise<Address> => {
// return readContract(config, {
// address: BackersManagerAddress,
// abi: BuilderRegistryAbi,
// functionName: 'builderToGauge',
// args: [builderAddress],
// })
// }
// const getBuilderState = async (gauge: Address): Promise<BuilderStateStruct> => {
// return readContract(config, {
// address: gauge,
// abi: GaugeAbi,
// functionName: 'builderState',
// })
// }
// const getBuilderStatus = async (builderAddress: Address): Promise<BuilderStatusWithExcluded> => {
// const gauge = await getBuilderGauge(builderAddress)
// const builderState = await getBuilderState(gauge)
// return getCombinedBuilderStatus(builderState)
// }
// const getBuilders = async () => {
// const builders = await Promise.all(
// whitelistedBuilders.map(async builder => {
// const status = await getBuilderStatus(builder.address)
// return {
// ...builder,
// status,
// }
// }),
// )
// setBuilders(builders)
// }
// getBuilders()
// }, [builders])

function addSelectedBuilder(builderAddress: Address, isSelected: boolean) {
const index = activeBuilders.findIndex(builder => builder.address === builderAddress)

setSelectedBuilders({
...selectedBuilders,
[builderAddress]: {
index,
hasAllocationsByUser: (onchianAllocations && onchianAllocations[index]) ?? false,
isSelected,
},
})
}

const configActions = {
toggleSelectedBuilder: (builderAddress: Address, isSelected: boolean) => {
const existingSelection = selectedBuilders[builderAddress]
if (existingSelection) {
return setSelectedBuilders({
...selectedBuilders,
[builderAddress]: {
...existingSelection,
isSelected,
},
})
}

addSelectedBuilder(builderAddress, isSelected)
},
}

const configA = {
selectedBuilders,
...configActions,
}

const value: AllocationsContextValue = {
// buildersByAddress: whitelistedBuilders.reduce(
// (acc, builder) => {
// acc[builder.address] = builder
// return acc
// },
// {} as Record<Address, BuilderInfo>,
// ),
// isLoading,
// user: {
// address,
// backees: [],
// isBacker: false,
// },
// actions: {
// updateBacking: () => {},
// },
}
return withPagination(AllocationsContext.Provider)({
data: activeBuilders,
pageSize: 10,
currentPage: 0,
props: { value, children },
})
}
1 change: 1 addition & 0 deletions src/app/collective-rewards/allocations/context/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './AllocationsContext'
1 change: 1 addition & 0 deletions src/app/collective-rewards/allocations/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './useBackerTotalAllocation'
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { BackersManagerAbi } from '@/lib/abis/v2/BackersManagerAbi'
import { GaugeAbi } from '@/lib/abis/v2/GaugeAbi'
import { AVERAGE_BLOCKTIME } from '@/lib/constants'
import { BackersManagerAddress } from '@/lib/contracts'
import { Address } from 'viem'
import { useReadContract, useReadContracts } from 'wagmi'

export const useBackerTotalAllocation = (backer: Address) => {
const { data, isLoading, error } = useReadContract({
abi: BackersManagerAbi,
address: BackersManagerAddress,
functionName: 'backerTotalAllocation',
args: [backer],
query: {
refetchInterval: AVERAGE_BLOCKTIME,
initialData: 0n,
},
})

return {
data,
isLoading,
error,
}
}

export const useGetAllAllocationOf = (backer: Address, gauges: Address[]) => {
const { data, isLoading, error } = useReadContracts({
contracts: gauges.map(gauge => ({
abi: GaugeAbi,
address: gauge,
functionName: 'allocationOf',
args: [backer],
})),
query: {
refetchInterval: AVERAGE_BLOCKTIME,
},
})

return {
data,
isLoading,
error,
}
}
2 changes: 2 additions & 0 deletions src/app/collective-rewards/allocations/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './context'
export * from './hooks'
6 changes: 3 additions & 3 deletions src/app/collective-rewards/allocations/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import { MainContainer } from '@/components/MainContainer/MainContainer'
import { Typography } from '@/components/Typography'
import { AllocationAmount } from './AllocationAmount'
import { AllocationMetrics } from './AllocationMetrics'
import { BuilderAllocation } from './BuilderAllocation'
import { AllocationAmount } from './components/AllocationAmount'
import { AllocationMetrics } from './components/AllocationMetrics'
import { BuilderAllocation } from './components/BuilderAllocation'
import { Header } from './Header'
import { BuilderAllocationProps } from './types'
import { useState } from 'react'
Expand Down
72 changes: 72 additions & 0 deletions src/app/collective-rewards/context/PaginatedDataContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Context, createContext, FC, useContext, useEffect, useState } from 'react'

type PaginationConfig<T> = {
data: T[]
pageSize: number
currentPage: number
}

type PaginatedData<T extends Object = {}> = PaginationConfig<T> & {
getDataIndex: (index: number) => number
updateData: (data: T[]) => void
updatePageSize: (pageSize: number) => void
updateCurrentPage: (currentPage: number) => void
}

export const PaginatedDataContext = createContext<PaginatedData<any>>({
data: [],
pageSize: 0,
currentPage: 0,
getDataIndex: () => 0,
updateData: () => {},
updatePageSize: () => {},
updateCurrentPage: () => {},
})

export const usePaginatedDataContext = <T extends Object = {}>() => {
const context = useContext<PaginatedData<T>>(PaginatedDataContext)
if (!context) {
throw new Error('usePaginatedDataContext must be used within a PaginatedDataContextProvider')
}
return context
}

type PaginatedDataContextProviderProps<T extends Object = {}> = {
children: React.ReactNode
config: PaginationConfig<T>
}

export const PaginatedDataContextProvider: FC<PaginatedDataContextProviderProps> = ({ children, config }) => {
const [data, setData] = useState(config.data)
const [pageSize, setPageSize] = useState(config.pageSize)
const [currentPage, setCurrentPage] = useState(config.currentPage)

const contextMethods = {
getDataIndex: (pagedIndex: number) => pagedIndex + pageSize * currentPage,
updateData: (newData: typeof data) => setData(newData),
updatePageSize: (newPageSize: number) => setPageSize(newPageSize),
updateCurrentPage: (newCurrentPage: number) => setCurrentPage(newCurrentPage),
}

return (
<PaginatedDataContext.Provider value={{ data, pageSize, currentPage, ...contextMethods }}>
{children}
</PaginatedDataContext.Provider>
)
}

export const withPagination = <T extends Object = {}, TProps extends Object = {}>(
Component: FC<TProps>,
): FC<
PaginationConfig<T> & {
props: TProps
}
> => {
return ({ props, ...rest }) => {
return (
<PaginatedDataContextProvider config={{ ...rest }}>
<Component {...props} />
</PaginatedDataContextProvider>
)
}
}
Loading

0 comments on commit aebbe2c

Please sign in to comment.