Skip to content

Commit fd8bebe

Browse files
authored
Merge pull request #1489 from curvefi/feat/merkl
feat: add merkl rewards
2 parents 2caf247 + 7844e34 commit fd8bebe

File tree

28 files changed

+376
-670
lines changed

28 files changed

+376
-670
lines changed

apps/main/src/dex/components/PagePool/PoolDetails/PoolStats/Rewards.tsx

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ import Tooltip from '@ui/Tooltip/TooltipButton'
1717
import IconTooltip from '@ui/Tooltip/TooltipIcon'
1818
import { Chip } from '@ui/Typography'
1919
import { FORMAT_OPTIONS, formatNumber } from '@ui/utils'
20-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
20+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
2121
import { t } from '@ui-kit/lib/i18n'
22-
import { copyToClipboard } from '@ui-kit/utils'
22+
import { copyToClipboard, type Address } from '@ui-kit/utils'
2323

2424
type RewardsProps = {
2525
chainId: ChainId
@@ -31,8 +31,10 @@ const Rewards = ({ chainId, poolData, rewardsApy }: RewardsProps) => {
3131
const { base, other } = rewardsApy ?? {}
3232
const { haveBase, haveOther, haveCrv } = haveRewardsApy(rewardsApy ?? {})
3333
const network = useStore((state) => state.networks.networks[chainId])
34-
const { data: campaigns } = useCampaignsByNetwork(network.networkId as Chain)
35-
const campaignRewardsPool = campaigns?.[poolData.pool.address]
34+
const { data: campaigns } = useCampaignsByAddress({
35+
blockchainId: network.networkId as Chain,
36+
address: poolData.pool.address as Address,
37+
})
3638
const { isLite, scanTokenPath } = useStore((state) => state.networks.networks[chainId])
3739

3840
const baseAPYS = [
@@ -135,10 +137,10 @@ const Rewards = ({ chainId, poolData, rewardsApy }: RewardsProps) => {
135137
)}
136138
</RewardsContainer>
137139
)}
138-
{campaignRewardsPool && (
140+
{campaigns.length > 0 && (
139141
<CampaignRewardsWrapper>
140142
<h4>{t`Additional external rewards`}</h4>
141-
<CampaignRewardsRow rewardItems={campaignRewardsPool} />
143+
<CampaignRewardsRow rewardItems={campaigns} />
142144
</CampaignRewardsWrapper>
143145
)}
144146
</RewardsWrapper>

apps/main/src/dex/components/PagePool/components/CampaignRewardsBanner.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import CampaignBannerComp from 'ui/src/CampaignRewards/CampaignBannerComp'
33
import useStore from '@/dex/store/useStore'
44
import type { ChainId } from '@/dex/types/main.types'
55
import type { Chain } from '@curvefi/prices-api'
6-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
6+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
77
import { t } from '@ui-kit/lib/i18n'
8+
import type { Address } from '@ui-kit/utils'
89

910
interface CampaignRewardsBannerProps {
1011
chainId: ChainId
@@ -13,15 +14,17 @@ interface CampaignRewardsBannerProps {
1314

1415
const CampaignRewardsBanner = ({ chainId, address }: CampaignRewardsBannerProps) => {
1516
const network = useStore((state) => state.networks.networks[chainId])
16-
const { data: campaigns } = useCampaignsByNetwork(network.networkId as Chain)
17-
const campaignRewardsPool = campaigns?.[address] ?? []
18-
const message = campaignRewardsPool.some((rewardItem) => rewardItem.tags.includes('points'))
17+
const { data: campaigns } = useCampaignsByAddress({
18+
blockchainId: network.networkId as Chain,
19+
address: address as Address,
20+
})
21+
const message = campaigns.some((campaign) => campaign.tags.includes('points'))
1922
? t`Liquidity providers in this pool also earn points!`
2023
: t`Liquidity providers in this pool also earn additional tokens!`
2124
return (
22-
campaignRewardsPool.length > 0 && (
25+
campaigns.length > 0 && (
2326
<CampaignRewardsBannerWrapper>
24-
<CampaignBannerComp campaignRewardsPool={campaignRewardsPool} message={message} />
27+
<CampaignBannerComp campaignRewardsPool={campaigns} message={message} />
2528
</CampaignRewardsBannerWrapper>
2629
)
2730
)

apps/main/src/dex/components/PagePoolList/components/TableRow.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ import { PoolData, PoolDataCache, RewardsApy, Tvl, Volume } from '@/dex/types/ma
1313
import type { Chain } from '@curvefi/prices-api'
1414
import Box from '@ui/Box'
1515
import { CellInPool, Td, Tr } from '@ui/Table'
16-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
16+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
1717
import useIntersectionObserver from '@ui-kit/hooks/useIntersectionObserver'
1818
import { t } from '@ui-kit/lib/i18n'
19+
import type { Address } from '@ui-kit/utils'
1920

2021
export type TableRowProps = {
2122
index: number
@@ -58,7 +59,10 @@ const TableRow = ({
5859
}: TableRowProps) => {
5960
const { searchTextByTokensAndAddresses, searchTextByOther } = formValues
6061
const { searchText, sortBy } = searchParams
61-
const { data: campaigns } = useCampaignsByNetwork(blockchainId as Chain)
62+
const { data: campaigns } = useCampaignsByAddress({
63+
blockchainId: blockchainId as Chain,
64+
address: poolData?.pool?.address as Address,
65+
})
6266

6367
return (
6468
<LazyItem id={`${poolId}-${index}`} className="row--info" onClick={({ target }) => handleCellClick(target)}>
@@ -97,9 +101,7 @@ const TableRow = ({
97101
<TableCellRewardsOthers isHighlight={sortBy === 'rewardsOther'} rewardsApy={rewardsApy} />
98102
</>
99103
)}
100-
{poolData && campaigns?.[poolData.pool.address] && (
101-
<CampaignRewardsRow rewardItems={campaigns[poolData.pool.address]} />
102-
)}
104+
{campaigns.length > 0 && <CampaignRewardsRow rewardItems={campaigns} />}
103105
</Box>
104106
</Td>
105107
)}
@@ -124,9 +126,7 @@ const TableRow = ({
124126
{rewardsApy && (
125127
<TableCellRewardsOthers isHighlight={sortBy === 'rewardsOther'} rewardsApy={rewardsApy} />
126128
)}
127-
{poolData && campaigns?.[poolData.pool.address] && (
128-
<CampaignRewardsRow rewardItems={campaigns[poolData.pool.address]} />
129-
)}
129+
{campaigns.length > 0 && <CampaignRewardsRow rewardItems={campaigns} />}
130130
</Box>
131131
</Td>
132132
</>
@@ -141,9 +141,7 @@ const TableRow = ({
141141
isHighlightOther={sortBy === 'rewardsOther'}
142142
rewardsApy={rewardsApy}
143143
/>
144-
{poolData && campaigns?.[poolData.pool.address] && (
145-
<CampaignRewardsRow rewardItems={campaigns[poolData.pool.address]} />
146-
)}
144+
{campaigns.length > 0 && <CampaignRewardsRow rewardItems={campaigns} />}
147145
</Box>
148146
</Td>
149147
)}

apps/main/src/dex/components/PagePoolList/components/TableRowMobile.tsx

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ import IconButton from '@ui/IconButton'
1919
import ListInfoItem, { ListInfoItems } from '@ui/ListInfo'
2020
import { CellInPool } from '@ui/Table'
2121
import { formatNumber } from '@ui/utils'
22-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
22+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
2323
import { t } from '@ui-kit/lib/i18n'
2424
import type { ThemeKey } from '@ui-kit/themes/basic-theme'
25+
import type { Address } from '@ui-kit/utils'
2526

2627
type TableRowMobileProps = Omit<TableRowProps, 'isMdUp'> & {
2728
showDetail: string
@@ -51,7 +52,10 @@ const TableRowMobile = ({
5152
handleCellClick,
5253
setShowDetail,
5354
}: TableRowMobileProps) => {
54-
const { data: campaigns } = useCampaignsByNetwork(blockchainId as Chain)
55+
const { data: campaigns } = useCampaignsByAddress({
56+
blockchainId: blockchainId as Chain,
57+
address: poolData?.pool?.address as Address,
58+
})
5559
const { searchTextByTokensAndAddresses, searchTextByOther } = formValues
5660
const { searchText, sortBy } = searchParams
5761
const isShowDetail = showDetail === poolId
@@ -152,9 +156,9 @@ const TableRowMobile = ({
152156
/>
153157
</ListInfoItem>
154158
)}
155-
{poolData && campaigns?.[poolData.pool.address] && (
159+
{campaigns.length > 0 && (
156160
<ListInfoItem title={t`Additional external rewards`}>
157-
<CampaignRewardsRow rewardItems={campaigns[poolData.pool.address]} mobile />
161+
<CampaignRewardsRow rewardItems={campaigns} mobile />
158162
</ListInfoItem>
159163
)}
160164
</>

apps/main/src/dex/store/createPoolListSlice.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import {
2424
type ValueMapperCached,
2525
} from '@/dex/types/main.types'
2626
import type { Chain } from '@curvefi/prices-api'
27-
import { getCampaigns } from '@ui-kit/entities/campaigns'
27+
import { combineCampaigns } from '@ui-kit/entities/campaigns'
28+
import { getCampaignsExternal } from '@ui-kit/entities/campaigns/campaigns-external'
29+
import { getCampaignsMerkl } from '@ui-kit/entities/campaigns/campaigns-merkl'
2830
import { groupSearchTerms, searchByText, takeTopWithMin } from '@ui-kit/utils'
2931

3032
type StateKey = keyof typeof DEFAULT_STATE
@@ -201,13 +203,20 @@ const createPoolListSlice = (set: SetState<State>, get: GetState<State>): PoolLi
201203
const blockchainId = networks[chainId].networkId as Chain
202204
return orderBy(
203205
poolDatas,
204-
({ pool }) =>
205-
Math.max(
206+
({ pool }) => {
207+
const externalCampaigns = getCampaignsExternal({})
208+
const merklCampaigns = getCampaignsMerkl({})
209+
const campaigns = combineCampaigns({
210+
campaigns: [externalCampaigns, merklCampaigns],
211+
filter: (campaign) => campaign.network === blockchainId,
212+
})
213+
const rewards = campaigns[pool.address.toLowerCase()] ?? []
214+
215+
return Math.max(
206216
0,
207-
...(getCampaigns({})?.[pool.address.toLowerCase()] ?? [])
208-
.filter((x) => x.network === blockchainId)
209-
.map((x) => (x.multiplier && typeof x.multiplier === 'number' ? x.multiplier : 0)),
210-
),
217+
...rewards.map((x) => (x.multiplier && typeof x.multiplier === 'number' ? x.multiplier : 0)),
218+
)
219+
},
211220
[order],
212221
)
213222
}

apps/main/src/lend/components/CampaignRewardsBanner.tsx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import CampaignBannerComp from 'ui/src/CampaignRewards/CampaignBannerComp'
22
import networks from '@/lend/networks'
33
import { ChainId } from '@/lend/types/lend.types'
44
import type { Chain } from '@curvefi/prices-api'
5-
import { useCampaigns } from '@ui-kit/entities/campaigns'
5+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
66
import { t } from '@ui-kit/lib/i18n'
7+
import type { Address } from '@ui-kit/utils'
78

89
interface CampaignRewardsBannerProps {
910
chainId: ChainId
@@ -13,17 +14,17 @@ interface CampaignRewardsBannerProps {
1314

1415
const CampaignRewardsBanner = ({ chainId, borrowAddress, supplyAddress }: CampaignRewardsBannerProps) => {
1516
const blockchainId = networks[chainId].id as Chain
16-
const { data: campaigns } = useCampaigns({ blockchainId })
17-
const supplyCampaignRewardsPool = campaigns?.[supplyAddress] ?? []
18-
const borrowCampaignRewardsPool = campaigns?.[borrowAddress] ?? []
17+
const { data: supplyCampaigns } = useCampaignsByAddress({ blockchainId, address: supplyAddress as Address })
18+
const { data: borrowCampaigns } = useCampaignsByAddress({ blockchainId, address: borrowAddress as Address })
19+
1920
return (
20-
supplyCampaignRewardsPool.length + borrowCampaignRewardsPool.length > 0 && (
21+
supplyCampaigns.length + borrowCampaigns.length > 0 && (
2122
<CampaignBannerComp
22-
campaignRewardsPool={[...supplyCampaignRewardsPool, ...borrowCampaignRewardsPool]}
23+
campaignRewardsPool={[...supplyCampaigns, ...borrowCampaigns]}
2324
message={
24-
supplyCampaignRewardsPool.length && borrowCampaignRewardsPool.length
25+
supplyCampaigns.length && borrowCampaigns.length
2526
? t`Supplying and borrowing in this pool earns points!`
26-
: supplyCampaignRewardsPool
27+
: supplyCampaigns
2728
? t`Supplying in this pool earns points!`
2829
: t`Borrowing in this pool earns points!`
2930
}

apps/main/src/lend/hooks/useBorrowPositionDetails.ts

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { BorrowPositionDetailsProps } from '@/llamalend/features/market-pos
99
import { calculateRangeToLiquidation } from '@/llamalend/features/market-position-details/utils'
1010
import { calculateLtv } from '@/llamalend/llama.utils'
1111
import type { Address, Chain } from '@curvefi/prices-api'
12-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
12+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
1313
import { useLendingSnapshots } from '@ui-kit/entities/lending-snapshots'
1414
import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate'
1515
import { LlamaMarketType } from '@ui-kit/types/market'
@@ -48,7 +48,7 @@ export const useBorrowPositionDetails = ({
4848
const prices = useStore((state) => state.markets.pricesMapper[chainId]?.[marketId])
4949

5050
const blockchainId = networks[chainId].id as Chain
51-
const { data: campaigns } = useCampaignsByNetwork(blockchainId)
51+
const { data: campaigns } = useCampaignsByAddress({ blockchainId, address: controller as Address })
5252
const { data: onChainRatesData, isLoading: isOnchainRatesLoading } = useMarketOnChainRates({
5353
chainId,
5454
marketId,
@@ -82,10 +82,6 @@ export const useBorrowPositionDetails = ({
8282
if (!collateralUsdRate || !collateral || !borrowed) return null
8383
return Number(collateral) * Number(collateralUsdRate) + Number(borrowed)
8484
}, [collateral, borrowed, collateralUsdRate])
85-
const campaignRewards = useMemo(() => {
86-
if (!campaigns || !controller) return []
87-
return [...(campaigns[controller.toLowerCase()] ?? [])]
88-
}, [campaigns, controller])
8985

9086
const rebasingYield = lendSnapshots?.[lendSnapshots.length - 1]?.collateralToken?.rebasingYield // take most recent rebasing yield
9187
return {
@@ -106,7 +102,7 @@ export const useBorrowPositionDetails = ({
106102
averageRebasingYield: averageRebasingYield ?? null,
107103
totalBorrowRate: borrowApy == null ? null : Number(borrowApy) - (rebasingYield ?? 0),
108104
totalAverageBorrowRate: averageRate == null ? null : averageRate - (averageRebasingYield ?? 0),
109-
extraRewards: campaignRewards,
105+
extraRewards: campaigns,
110106
loading: !market || isOnchainRatesLoading || isLendSnapshotsLoading || !market?.addresses.controller,
111107
},
112108
liquidationRange: {

apps/main/src/lend/hooks/useMarketDetails.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import useStore from '@/lend/store/useStore'
66
import type { ChainId, OneWayMarketTemplate } from '@/lend/types/lend.types'
77
import type { MarketDetailsProps } from '@/llamalend/features/market-details'
88
import type { Chain, Address } from '@curvefi/prices-api'
9-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
9+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
1010
import { useLendingSnapshots } from '@ui-kit/entities/lending-snapshots'
1111
import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate'
1212
import { LlamaMarketType } from '@ui-kit/types/market'
@@ -51,7 +51,10 @@ export const useMarketDetails = ({
5151
chainId,
5252
tokenAddress: borrowed_token?.address,
5353
})
54-
const { data: campaigns } = useCampaignsByNetwork(blockchainId)
54+
55+
const { data: campaignsVault } = useCampaignsByAddress({ blockchainId, address: vault as Address })
56+
const { data: campaignsController } = useCampaignsByAddress({ blockchainId, address: controller as Address })
57+
const campaigns = [...campaignsVault, ...campaignsController]
5558

5659
const {
5760
borrowApy: averageBorrowApy,
@@ -89,10 +92,6 @@ export const useMarketDetails = ({
8992
const supplyAprCrvMaxBoost = crvRates?.[1] ?? lendingSnapshots?.[0]?.lendAprCrvMaxBoost ?? 0
9093
const collateralRebasingYield = lendingSnapshots?.[lendingSnapshots.length - 1]?.collateralToken?.rebasingYield // take only most recent rebasing yield
9194
const borrowRebasingYield = lendingSnapshots?.[lendingSnapshots.length - 1]?.borrowedToken?.rebasingYield // take only most recent rebasing yield
92-
const campaignRewards =
93-
campaigns && vault && controller
94-
? [...(campaigns[vault.toLowerCase()] ?? []), ...(campaigns[controller.toLowerCase()] ?? [])]
95-
: []
9695
const extraIncentivesTotalApr = sum(rewardsApr?.map((r) => r.apy) ?? [])
9796
const totalSupplyRateMinBoost =
9897
supplyApy == null
@@ -145,7 +144,7 @@ export const useMarketDetails = ({
145144
averageRebasingYield: averageBorrowRebasingYield ?? null,
146145
totalBorrowRate: borrowApy == null ? null : Number(borrowApy) - (collateralRebasingYield ?? 0),
147146
totalAverageBorrowRate,
148-
extraRewards: campaignRewards,
147+
extraRewards: campaigns,
149148
loading: !llamma || isSnapshotsLoading || isMarketDetailsLoading.marketOnChainRates,
150149
},
151150
supplyAPY: {
@@ -171,7 +170,7 @@ export const useMarketDetails = ({
171170
address: r.tokenAddress,
172171
}))
173172
: [],
174-
extraRewards: campaignRewards,
173+
extraRewards: campaigns,
175174
loading: !llamma || isSnapshotsLoading || isMarketDetailsLoading.marketOnChainRates,
176175
},
177176
availableLiquidity: {

apps/main/src/lend/hooks/useSupplyPositionDetails.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import networks from '@/lend/networks'
66
import { ChainId, OneWayMarketTemplate } from '@/lend/types/lend.types'
77
import type { SupplyPositionDetailsProps } from '@/llamalend/features/market-position-details'
88
import type { Address, Chain } from '@curvefi/prices-api'
9-
import { useCampaignsByNetwork } from '@ui-kit/entities/campaigns'
9+
import { useCampaignsByAddress } from '@ui-kit/entities/campaigns'
1010
import { useLendingSnapshots } from '@ui-kit/entities/lending-snapshots'
1111
import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate'
1212
import { calculateAverageRates } from '@ui-kit/utils/averageRates'
@@ -26,7 +26,10 @@ export const useSupplyPositionDetails = ({
2626
marketId,
2727
}: UseSupplyPositionDetailsProps): SupplyPositionDetailsProps => {
2828
const blockchainId = networks[chainId].id as Chain
29-
const { data: campaigns } = useCampaignsByNetwork(blockchainId)
29+
const { data: campaigns } = useCampaignsByAddress({
30+
blockchainId,
31+
address: market?.addresses?.vault?.toLocaleLowerCase() as Address,
32+
})
3033
const { data: userBalances, isLoading: isUserBalancesLoading } = useUserMarketBalances({ chainId, marketId })
3134
const { data: marketPricePerShare, isLoading: isMarketPricePerShareLoading } = useMarketPricePerShare({
3235
chainId,
@@ -103,11 +106,6 @@ export const useSupplyPositionDetails = ({
103106
(averageTotalExtraIncentivesApr ?? 0) +
104107
(averageSupplyAprCrvMaxBoost ?? 0)
105108

106-
const campaignRewards = useMemo(() => {
107-
if (!campaigns || !market?.addresses?.vault) return []
108-
return [...(campaigns[market?.addresses?.vault.toLowerCase()] ?? [])]
109-
}, [campaigns, market?.addresses?.vault])
110-
111109
return {
112110
supplyAPY: {
113111
rate: supplyApy,
@@ -134,7 +132,7 @@ export const useSupplyPositionDetails = ({
134132
}))
135133
: [],
136134
averageTotalExtraIncentivesApr: averageTotalExtraIncentivesApr ?? null,
137-
extraRewards: campaignRewards,
135+
extraRewards: campaigns,
138136
loading: islendingSnapshotsLoading || isOnChainRatesLoading || isUserBalancesLoading,
139137
},
140138
boost: {

0 commit comments

Comments
 (0)