Skip to content

Commit 6a64b68

Browse files
Merge pull request #4941 from VenusProtocol/feat/off-chain-apy
feat: support off-chain APYs
2 parents 9ddded0 + f2e19a6 commit 6a64b68

File tree

8 files changed

+73
-21
lines changed

8 files changed

+73
-21
lines changed

.changeset/major-views-nail.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@venusprotocol/evm": minor
3+
---
4+
5+
Support off-chain APYs

apps/evm/src/clients/api/queries/useGetPools/getPools/formatOutput/formatDistributions/formatRewardDistribution/index.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type BigNumber from 'bignumber.js';
22

33
import type {
4-
IntrinsicApyDistribution,
4+
GenericDistribution,
55
MerklDistribution,
66
RewardDistributorDistribution,
77
Token,
@@ -18,23 +18,27 @@ interface MerklRewardDetails {
1818
tags: string[];
1919
}
2020

21-
interface IntrinsicApyRewardDetails {
21+
interface GenericDistributionRewardDetails {
2222
name: string;
2323
description: string;
2424
}
2525

26-
type FormatDistributionInput<TType extends 'venus' | 'merkl' | 'intrinsic'> = {
26+
type ApiRewardType = 'venus' | 'merkl' | 'intrinsic' | 'off-chain';
27+
28+
type FormatDistributionInput<TType extends ApiRewardType> = {
2729
rewardType: TType;
2830
isActive: boolean;
2931
marketAddress: Address;
3032
rewardToken: Token;
3133
rewardTokenPriceDollars: BigNumber;
3234
dailyDistributedRewardTokens: BigNumber;
3335
balanceDollars: BigNumber;
34-
rewardDetails: TType extends 'merkl' ? MerklRewardDetails : IntrinsicApyRewardDetails | null;
36+
rewardDetails: TType extends 'merkl'
37+
? MerklRewardDetails
38+
: GenericDistributionRewardDetails | null;
3539
};
3640

37-
const formatRewardDistribution = <TType extends 'venus' | 'merkl' | 'intrinsic'>({
41+
const formatRewardDistribution = <TType extends ApiRewardType>({
3842
marketAddress,
3943
isActive,
4044
rewardType,
@@ -75,12 +79,12 @@ const formatRewardDistribution = <TType extends 'venus' | 'merkl' | 'intrinsic'>
7579
return distribution;
7680
}
7781

78-
if (rewardType === 'intrinsic' && rewardDetails) {
79-
const distribution: IntrinsicApyDistribution = {
82+
if ((rewardType === 'intrinsic' || rewardType === 'off-chain') && rewardDetails) {
83+
const distribution: GenericDistribution = {
8084
...baseProps,
81-
type: 'intrinsic',
85+
type: rewardType,
8286
isActive,
83-
rewardDetails: rewardDetails as IntrinsicApyRewardDetails,
87+
rewardDetails: rewardDetails as GenericDistributionRewardDetails,
8488
};
8589

8690
return distribution;

apps/evm/src/clients/api/queries/useGetPools/getPools/getApiPools/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ interface ApiIntrinsicApyReward extends ApiReward {
4040
};
4141
}
4242

43+
type ApiOffChainApyReward = Omit<ApiIntrinsicApyReward, 'type'> & {
44+
rewardType: 'intrinsic';
45+
};
46+
4347
export type PointsProgram = 'ethena' | 'etherfi' | 'kelp' | 'solv' | 'aster';
4448

4549
export interface ApiPointsDistribution {
@@ -54,7 +58,11 @@ export interface ApiPointsDistribution {
5458
logoUrl?: string;
5559
}
5660

57-
export type ApiRewardDistributor = ApiVenusReward | ApiMerklReward | ApiIntrinsicApyReward;
61+
export type ApiRewardDistributor =
62+
| ApiVenusReward
63+
| ApiMerklReward
64+
| ApiIntrinsicApyReward
65+
| ApiOffChainApyReward;
5866

5967
export interface ApiMarketEModeSettings {
6068
marketAddress: Address;

apps/evm/src/components/Apy/BoostTooltip/index.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ export const BoostTooltip: React.FC<BoostTooltipProps> = ({
3636
{
3737
name:
3838
type === 'supply'
39-
? t('apy.boost.tooltip.baseSupplyApyLabel')
40-
: t('apy.boost.tooltip.baseBorrowApyLabel'),
39+
? t('apy.boost.tooltip.supplyApy.name')
40+
: t('apy.boost.tooltip.borrowApy.name'),
4141
value: formatPercentageToReadableValue(baseApyPercentage),
4242
logoSrc: token.iconSrc,
43+
description:
44+
type === 'supply'
45+
? t('apy.boost.tooltip.supplyApy.description')
46+
: t('apy.boost.tooltip.borrowApy.description'),
4347
},
4448
];
4549

@@ -94,6 +98,17 @@ export const BoostTooltip: React.FC<BoostTooltipProps> = ({
9498

9599
return listItems.push(distribution);
96100
}
101+
102+
if (d.type === 'off-chain') {
103+
const distribution: DistributionProps = {
104+
name: t('apy.boost.tooltip.offChainApy.name'),
105+
description: t('apy.boost.tooltip.offChainApy.description'),
106+
value: formatPercentageToReadableValue(d.apyPercentage),
107+
logoSrc: d.token.iconSrc,
108+
};
109+
110+
return listItems.push(distribution);
111+
}
97112
}, []);
98113

99114
// Add Prime distribution

apps/evm/src/libs/translations/translations/en.json

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,21 +177,31 @@
177177
"boost": {
178178
"iconAlt": "Boosted market icon",
179179
"tooltip": {
180-
"baseBorrowApyLabel": "Borrow APY",
181-
"baseSupplyApyLabel": "Supply APY",
180+
"borrowApy": {
181+
"description": "The accruing interest when borrowing this asset from the Venus Protocol.",
182+
"name": "Borrow APY"
183+
},
182184
"defaultMerklRewardName": "Merkl rewards",
183185
"externalRewardDescription": "Rewards from this external program can be claimed through their <AppLink>official app</AppLink>. The Venus protocol does not guarantee them and accepts no liability.",
184186
"intrinsicApy": {
185-
"description": "Yield generated by the supplied asset, independent of lending yield from Venus. Commonly from staking or other external rewards.",
187+
"description": "The native yield from the underlying asset itself — for example, staking rewards. This yield originates from external sources and is not guaranteed by Venus Protocol.",
186188
"name": "Intrinsic APY"
187189
},
190+
"offChainApy": {
191+
"description": "Additional yield from off-chain activities, such as airdrop or promotional campaigns, managed by third parties. This yield is not guaranteed by Venus Protocol.",
192+
"name": "Off-chain APY"
193+
},
188194
"pointDistribution": {
189195
"learnMore": "Learn more"
190196
},
191197
"primeDistribution": {
192198
"description": "Venus Prime rewards dedicated users with boosted rewards. The Venus protocol does not guarantee these rewards and accepts no liability.",
193199
"name": "Prime APY"
194200
},
201+
"supplyApy": {
202+
"description": "The total yield earned by supplying your asset to Venus Protocol.",
203+
"name": "Supply APY"
204+
},
195205
"xvsDistribution": {
196206
"description": "Distribution rewards are initiated and implemented by the decentralized Venus community. The Venus protocol does not guarantee them and accepts no liability.",
197207
"name": "XVS distribution"
@@ -239,11 +249,13 @@
239249
},
240250
"assetInfo": {
241251
"borrowApy": "Borrow APY",
242-
"intrinsicApy": "Intrinsic APY ({{tokenSymbol}})",
243252
"distributionApy": "Distribution APY ({{tokenSymbol}})",
244253
"distributionTooltip": "Distribution rewards are initiated and implemented by the decentralized Venus community. The Venus protocol does not guarantee them and accepts no liability.",
245-
"intrinsicApyTooltip": "APY earned directly from the asset itself (e.g. staking or external rewards), separate from Venus lending yield. The Venus protocol does not guarantee them and accepts no liability.",
246254
"externalDistributionApy": "{{description}} APY ({{tokenSymbol}})",
255+
"intrinsicApy": "Intrinsic APY ({{tokenSymbol}})",
256+
"intrinsicApyTooltip": "APY earned directly from the asset itself (e.g. staking or external rewards), separate from Venus lending yield. The Venus protocol does not guarantee them and accepts no liability.",
257+
"offChainApy": "Off-chain APY ({{tokenSymbol}})",
258+
"offChainApyTooltip": "Additional yield from off-chain activities, such as airdrop or promotional campaigns, managed by third parties. The Venus protocol does not guarantee them and accepts no liability.",
247259
"primeApy": "Prime APY ({{tokenSymbol}})",
248260
"supplyApy": "Supply APY",
249261
"totalApy": {

apps/evm/src/pages/Market/OperationForm/AssetInfo/index.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@ export const AssetInfo: React.FC<AssetInfoProps> = ({
123123
if (distribution.type === 'intrinsic') {
124124
label = t('assetInfo.intrinsicApy', { tokenSymbol: distribution.token.symbol });
125125
}
126+
if (distribution.type === 'off-chain') {
127+
label = t('assetInfo.offChainApy', { tokenSymbol: distribution.token.symbol });
128+
}
126129
const children =
127130
distribution.type === 'prime' ? (
128131
<ValueUpdate
@@ -146,6 +149,9 @@ export const AssetInfo: React.FC<AssetInfoProps> = ({
146149
if (distribution.type === 'intrinsic') {
147150
tooltip = t('assetInfo.intrinsicApyTooltip');
148151
}
152+
if (distribution.type === 'off-chain') {
153+
tooltip = t('assetInfo.offChainApyTooltip');
154+
}
149155

150156
const row: LabeledInlineContentProps = {
151157
label,

apps/evm/src/types/index.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Token as PSToken } from '@pancakeswap/sdk';
22
import type { ChainId, Token, VToken } from '@venusprotocol/chains';
3+
import type { Omit } from '@wagmi/core/internal';
34
import type BigNumber from 'bignumber.js';
45
import type { Address, ByteArray, Hex } from 'viem';
56

@@ -85,8 +86,8 @@ export interface MerklDistribution {
8586
};
8687
}
8788

88-
export interface IntrinsicApyDistribution {
89-
type: 'intrinsic';
89+
export interface GenericDistribution {
90+
type: 'intrinsic' | 'off-chain';
9091
token: Token;
9192
apyPercentage: BigNumber;
9293
dailyDistributedTokens: BigNumber;
@@ -102,7 +103,7 @@ export type TokenDistribution =
102103
| PrimeDistribution
103104
| PrimeSimulationDistribution
104105
| MerklDistribution
105-
| IntrinsicApyDistribution;
106+
| GenericDistribution;
106107

107108
export interface PointDistribution {
108109
title: string;

apps/evm/src/utilities/getCombinedDistributionApys/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ const aggregatePercentages = ({ distributions }: AggregatePercentagesInput) =>
1616
if (
1717
distribution.type === 'venus' ||
1818
distribution.type === 'merkl' ||
19-
distribution.type === 'intrinsic'
19+
distribution.type === 'intrinsic' ||
20+
distribution.type === 'off-chain'
2021
) {
2122
return {
2223
...acc,

0 commit comments

Comments
 (0)