Skip to content

Commit

Permalink
feat(cr_v2): all time rewards
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscotobar committed Nov 12, 2024
1 parent e4162cb commit 05d10d5
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 11 deletions.
14 changes: 13 additions & 1 deletion src/app/collective-rewards/actions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import { Address } from 'viem'
import { SimplifiedRewardDistributorAddress } from '@/lib/contracts'
import { axiosInstance } from '@/lib/utils'
import { fetchNotifyRewardLogsByAddress, fetchRewardDistributedLogsByAddress } from '@/lib/endpoints'
import {
fetchBuilderRewardsClaimedLogsByAddress,
fetchNotifyRewardLogsByAddress,
fetchRewardDistributedLogsByAddress,
} from '@/lib/endpoints'

export const fetchRewardDistributedLogs = (fromBlock = 0) => {
return axiosInstance.get(
Expand All @@ -21,3 +25,11 @@ export const fetchNotifyRewardLogs = (gaugeAddress: Address, fromBlock = 0) => {
.replace('{{fromBlock}}', fromBlock.toString()),
)
}

export const fetchBuilderRewardsClaimed = (gaugeAddress: Address, fromBlock = 0) => {
return axiosInstance.get(
fetchBuilderRewardsClaimedLogsByAddress
.replace('{{address}}', gaugeAddress)
.replace('{{fromBlock}}', fromBlock.toString()),
)
}
87 changes: 87 additions & 0 deletions src/app/collective-rewards/rewards/AllTimeRewards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
formatMetrics,
MetricsCard,
MetricsCardTitle,
MetricsCardWithSpinner,
TokenMetricsCardRow,
useGetBuilderRewards,
useGetBuilderRewardsClaimedLogs,
} from '@/app/collective-rewards/rewards'
import { useHandleErrors } from '@/app/collective-rewards/utils'
import { formatBalanceToHuman } from '@/app/user/Balances/balanceUtils'
import { withSpinner } from '@/components/LoadingSpinner/withLoadingSpinner'
import { usePricesContext } from '@/shared/context/PricesContext'
import { FC } from 'react'
import { Address } from 'viem'

type Token = {
symbol: string
address: Address
}

type TokenRewardsMetricsProps = {
gauge: Address
currency?: string
token: {
symbol: string
address: Address
}
}

const TokenRewardsMetrics: FC<TokenRewardsMetricsProps> = ({
gauge,
token: { symbol, address },
currency = 'USD',
}) => {
const {
data: rewardsPerToken,
isLoading: logsLoading,
error: rewardsError,
} = useGetBuilderRewardsClaimedLogs(gauge)
const {
data: claimableRewards,
isLoading: claimableRewardsLoading,
error: claimableRewardsError,
} = useGetBuilderRewards(address, gauge)

const error = rewardsError ?? claimableRewardsError
useHandleErrors({ error, title: 'Error loading all time rewards' })

const { prices } = usePricesContext()

const totalClaimedRewards =
rewardsPerToken[address]?.reduce((acc, event) => {
const amount = event.args.amount_ ?? 0n
return acc + amount
}, 0n) ?? 0n

const totalRewards = totalClaimedRewards + (claimableRewards ?? 0n)
const totalRewardsInHuman = Number(formatBalanceToHuman(totalRewards))
const price = prices[symbol]?.price ?? 0

const { amount, fiatAmount } = formatMetrics(totalRewardsInHuman, price, symbol, currency)

return withSpinner(TokenMetricsCardRow)({
amount,
fiatAmount,
isLoading: logsLoading || claimableRewardsLoading,
})
}

type AllTimeRewardsProps = {
gauge: Address
currency?: string
data: {
[token: string]: Token
}
}

export const AllTimeRewards: FC<AllTimeRewardsProps> = ({ data: { rif, rbtc }, ...rest }) => {
return (
<MetricsCard borderless>
<MetricsCardTitle title="All time rewards" data-testid="AllTimeRewards" />
<TokenRewardsMetrics {...rest} token={rif} />
<TokenRewardsMetrics {...rest} token={rbtc} />
</MetricsCard>
)
}
10 changes: 5 additions & 5 deletions src/app/collective-rewards/rewards/ClaimableRewards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,14 @@ type Token = {
address: Address
}

type RewardsTokenMetricsProps = {
type TokenRewardsMetricsProps = {
builder: Address
gauge: Address
token: Token
currency?: string
}

const RewardsTokenMetrics: FC<RewardsTokenMetricsProps> = ({
const TokenRewardsMetrics: FC<TokenRewardsMetricsProps> = ({
builder,
gauge,
token: { address, symbol },
Expand Down Expand Up @@ -106,12 +106,12 @@ type ClaimableRewardsProps = {
}
}

export const ClaimableRewards: FC<ClaimableRewardsProps> = ({ data, ...rest }) => {
export const ClaimableRewards: FC<ClaimableRewardsProps> = ({ data: { rif, rbtc }, ...rest }) => {
return (
<MetricsCard borderless>
<MetricsCardTitle title="Claimable rewards" data-testid="ClaimableRewards" />
<RewardsTokenMetrics {...rest} token={data.rif} />
<RewardsTokenMetrics {...rest} token={data.rbtc} />
<TokenRewardsMetrics {...rest} token={rif} />
<TokenRewardsMetrics {...rest} token={rbtc} />
</MetricsCard>
)
}
7 changes: 3 additions & 4 deletions src/app/collective-rewards/rewards/LastCycleRewards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@ import {
getLastCycleRewards,
MetricsCard,
MetricsCardTitle,
MetricsCardWithSpinner,
TokenMetricsCardRow,
useGetNotifyRewardLogs,
} from '@/app/collective-rewards/rewards'
import { useHandleErrors } from '@/app/collective-rewards/utils'
import { formatBalanceToHuman } from '@/app/user/Balances/balanceUtils'
import { withSpinner } from '@/components/LoadingSpinner/withLoadingSpinner'
import { usePricesContext } from '@/shared/context/PricesContext'
import { FC, useEffect, useState } from 'react'
import { FC } from 'react'
import { Address } from 'viem'

type TokenRewardsProps = {
type TokenRewardsMetricsProps = {
gauge: Address
currency?: string
token: {
Expand All @@ -24,7 +23,7 @@ type TokenRewardsProps = {
}
}

const TokenRewardsMetrics: FC<TokenRewardsProps> = ({
const TokenRewardsMetrics: FC<TokenRewardsMetricsProps> = ({
gauge,
token: { symbol, address },
currency = 'USD',
Expand Down
3 changes: 2 additions & 1 deletion src/app/collective-rewards/rewards/MyRewards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
useClaimStateReporting,
LastCycleRewards,
ClaimableRewards,
AllTimeRewards,
} from '@/app/collective-rewards/rewards'
import { CycleContextProvider } from '@/app/collective-rewards/metrics'
import { PricesContextProvider } from '@/shared/context/PricesContext'
Expand Down Expand Up @@ -48,7 +49,7 @@ export const Rewards: FC<{ builder: Address; gauge: Address }> = ({ builder, gau
<ClaimableRewards builder={builder} gauge={gauge} data={data} />
<LastCycleRewards gauge={gauge} data={data} />
<div>Estimated Rewards</div>
<div>All time rewards</div>
<AllTimeRewards gauge={gauge} data={data} />
<div>All time share</div>
<Popover
disabled={isClaimFunctionReady}
Expand Down
1 change: 1 addition & 0 deletions src/app/collective-rewards/rewards/hooks/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './useClaimBuilderRewards'
export * from './useGetBuilderRewards'
export * from './useGetBuilderRewardsClaimedLogs'
export * from './useGetRewardDistributedLogs'
export * from './useGetTokenProjectedReward'
export * from './useGetNotifyRewardLogs'
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { useQuery } from '@tanstack/react-query'
import { fetchBuilderRewardsClaimed } from '@/app/collective-rewards/actions'
import { Address, getAddress, parseEventLogs } from 'viem'
import { GaugeAbi } from '@/lib/abis/v2/GaugeAbi'
import { AVERAGE_BLOCKTIME } from '@/lib/constants'

export type BuilderRewardsClaimedEventLog = ReturnType<
typeof parseEventLogs<typeof GaugeAbi, true, 'BuilderRewardsClaimed'>
>

export type BuilderClaimedRewardsPerToken = Record<Address, BuilderRewardsClaimedEventLog>

export const useGetBuilderRewardsClaimedLogs = (gauge: Address) => {
const { data, error, isLoading } = useQuery({
queryFn: async () => {
const { data } = await fetchBuilderRewardsClaimed(gauge)

const events = parseEventLogs({
abi: GaugeAbi,
logs: data,
eventName: 'BuilderRewardsClaimed',
})

return events.reduce<BuilderClaimedRewardsPerToken>((acc, log) => {
const rewardToken = getAddress(log.args.rewardToken_)
acc[rewardToken] = [...(acc[rewardToken] || []), log]

return acc
}, {})
},
queryKey: ['builderRewardsClaimedLogs', gauge],
refetchInterval: AVERAGE_BLOCKTIME,
initialData: {},
})

return {
data,
error,
isLoading,
}
}
1 change: 1 addition & 0 deletions src/app/collective-rewards/rewards/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './utils'
export * from './MyRewards'
export * from './LastCycleRewards'
export * from './ClaimableRewards'
export * from './AllTimeRewards'
3 changes: 3 additions & 0 deletions src/lib/endpoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ export const fetchRewardDistributedLogsByAddress = `/address/{{address}}/eventsB

const NOTIFY_REWARD_EVENT = '0x3c0f5c48b0ffa2c570c1a0f4fbf7b0f8982213afff9eb42cd258ead865cf3c9d'
export const fetchNotifyRewardLogsByAddress = `/address/{{address}}/eventsByTopic0?topic0=${NOTIFY_REWARD_EVENT}&chainId=${CHAIN_ID}&fromBlock={{fromBlock}}`

const BUILDER_REWARDS_CLAIMED_EVENT = 'c309438e69ba53ef6afef64839bd1ab1acc4a9a8fd28c8e0356075ca66f72c1b'
export const fetchBuilderRewardsClaimedLogsByAddress = `/address/{{address}}/eventsByTopic0?topic0=${BUILDER_REWARDS_CLAIMED_EVENT}&chainId=${CHAIN_ID}&fromBlock={{fromBlock}}`

0 comments on commit 05d10d5

Please sign in to comment.