Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/components/incentives/IncentivesTooltipContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,11 @@ const IncentivesSymbolMap: {
symbol: 'aEURC',
aToken: true,
},
aEthUSDe: {
tokenIconSymbol: 'USDe',
symbol: 'aUSDe',
aToken: true,
},
};

interface IncentivesTooltipContentProps {
Expand Down
29 changes: 21 additions & 8 deletions src/components/incentives/MerklIncentivesTooltipContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,34 @@ export const MerklIncentivesTooltipContent = ({
</Trans>
</Typography>

<Typography variant="caption" color="text.secondary" mb={3}>
<Typography variant="caption" color="text.strong" mb={3}>
<Trans>Merkl rewards are claimed through the</Trans>{' '}
<Link
href="https://app.merkl.xyz/"
sx={{ textDecoration: 'underline' }}
variant="caption"
color="text.secondary"
>
<Link href="https://app.merkl.xyz/" sx={{ textDecoration: 'underline' }} variant="caption">
official app
</Link>
{'.'}
{merklIncentives.customClaimMessage ? (
<>
{' '}
<Trans> {merklIncentives.customClaimMessage}</Trans>
</>
) : null}
</Typography>

{merklIncentives.customMessage ? (
<Typography variant="caption" color="text.strong" mb={3}>
<Trans>{merklIncentives.customMessage}</Trans>
<Trans>{merklIncentives.customMessage}</Trans>{' '}
<Link
href={
merklIncentives.customForumLink
? merklIncentives.customForumLink
: 'https://governance.aave.com/t/arfc-set-aci-as-emission-manager-for-liquidity-mining-programs/17898'
}
sx={{ textDecoration: 'underline' }}
variant="caption"
>
Learn more
</Link>
</Typography>
) : null}

Expand Down
28 changes: 21 additions & 7 deletions src/components/transactions/Swap/SwapModal.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { Trans } from '@lingui/macro';
import { Box, Typography } from '@mui/material';
import React from 'react';
import { BasicModal } from 'src/components/primitives/BasicModal';
import { UserAuthenticated } from 'src/components/UserAuthenticated';
import { ConnectWalletButton } from 'src/components/WalletConnection/ConnectWalletButton';
import { ModalContextType, ModalType, useModalContext } from 'src/hooks/useModal';
import { useRootStore } from 'src/store/root';

import { ModalWrapper } from '../FlowCommons/ModalWrapper';
import { SwapModalContent } from './SwapModalContent';
Expand All @@ -11,15 +14,26 @@ export const SwapModal = () => {
const { type, close, args } = useModalContext() as ModalContextType<{
underlyingAsset: string;
}>;
const account = useRootStore((store) => store.account);

return (
<BasicModal open={type === ModalType.Swap} setOpen={close}>
<ModalWrapper title={<Trans>Swap</Trans>} underlyingAsset={args.underlyingAsset}>
{(params) => (
<UserAuthenticated>
{(user) => <SwapModalContent {...params} user={user} />}
</UserAuthenticated>
)}
</ModalWrapper>
{!account ? (
<Box sx={{ display: 'flex', flexDirection: 'column', mt: 4, alignItems: 'center' }}>
<Typography sx={{ mb: 6, textAlign: 'center' }} color="text.secondary">
<Trans>Please connect your wallet to swap tokens.</Trans>
</Typography>
<ConnectWalletButton onClick={() => close()} />
</Box>
) : (
<ModalWrapper title={<Trans>Swap</Trans>} underlyingAsset={args.underlyingAsset}>
{(params) => (
<UserAuthenticated>
{(user) => <SwapModalContent {...params} user={user} />}
</UserAuthenticated>
)}
</ModalWrapper>
)}
</BasicModal>
);
};
2 changes: 1 addition & 1 deletion src/hooks/useEthenaIncentives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const getEthenaData = (assetAddress: string): number | undefined =>
ETHENA_DATA_MAP.get(assetAddress);

const ETHENA_DATA_MAP: Map<string, number> = new Map([
[AaveV3Ethereum.ASSETS.USDe.A_TOKEN, 25],
[AaveV3Ethereum.ASSETS.USDe.A_TOKEN, 5],
[AaveV3Ethereum.ASSETS.sUSDe.A_TOKEN, 5],
[AaveV3EthereumLido.ASSETS.sUSDe.A_TOKEN, 5],
[AaveV3Ethereum.ASSETS.GHO.V_TOKEN, 5],
Expand Down
66 changes: 56 additions & 10 deletions src/hooks/useMeritIncentives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,15 @@ export enum MeritAction {
AVALANCHE_SUPPLY_USDT = 'avalanche-supply-usdt',
AVALANCHE_SUPPLY_SAVAX = 'avalanche-supply-savax',
AVALANCHE_SUPPLY_AUSD = 'avalanche-supply-ausd',
AVALANCHE_SUPPLY_GHO = 'avalanche-supply-gho',
SONIC_SUPPLY_USDCE = 'sonic-supply-usdce',
SONIC_SUPPLY_STS_BORROW_WS = 'sonic-supply-sts-borrow-ws',
GNOSIS_BORROW_EURE = 'gnosis-borrow-eure',
CELO_SUPPLY_CELO = 'celo-supply-celo',
CELO_SUPPLY_USDT = 'celo-supply-usdt',
CELO_SUPPLY_USDC = 'celo-supply-usdc',
CELO_SUPPLY_WETH = 'celo-supply-weth',
CELO_SUPPLY_MULTIPLE_BORROW_USDT = 'celo-supply-multiple-borrow-usdt',
CELO_BORROW_CELO = 'celo-borrow-celo',
CELO_BORROW_USDT = 'celo-borrow-usdt',
CELO_BORROW_USDC = 'celo-borrow-usdc',
Expand Down Expand Up @@ -110,6 +112,9 @@ const baseIncentivesWstETHCampaignsMessage =
const baseIncentivesETHCampaignsMessage =
'Supplying ETH alone earns 1.25%, supplying ETH and borrowing USDC or EURC earns 1.50%, supplying ETH and borrowing GHO earns 1.75%. Some assets holding or positions on other protocols may impact the amount of rewards you are eligible for. Please check the forum post for the full eligibility criteria.';

const celoSupplyMultipleBorrowUsdtMessage =
'You must supply (CELO or ETH) and borrow USDT, in order to receive merit rewards. Please check the forum post for the full eligibility criteria.';

const joinedEthCorrelatedIncentiveForumLink =
'https://governance.aave.com/t/arfc-set-aci-as-emission-manager-for-liquidity-mining-programs/17898/56';

Expand Down Expand Up @@ -516,6 +521,15 @@ const MERIT_DATA_MAP: Record<string, Record<string, MeritReserveIncentiveData[]>
customForumLink: AusdRenewalForumLink,
},
],
GHO: [
{
action: MeritAction.AVALANCHE_SUPPLY_GHO,
rewardTokenAddress: AaveV3Avalanche.ASSETS.GHO.A_TOKEN,
rewardTokenSymbol: 'aAvaSAVAX',
Copy link

Copilot AI Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reward token symbol 'aAvaSAVAX' appears incorrect for a GHO supply action on Avalanche. This should likely be 'aAvaGHO' to match the GHO asset being supplied.

Suggested change
rewardTokenSymbol: 'aAvaSAVAX',
rewardTokenSymbol: 'aAvaGHO',

Copilot uses AI. Check for mistakes.
protocolAction: ProtocolAction.supply,
customMessage: antiLoopMessage,
},
],
},
[CustomMarket.proto_sonic_v3]: {
['USDC']: [
Expand Down Expand Up @@ -572,6 +586,13 @@ const MERIT_DATA_MAP: Record<string, Record<string, MeritReserveIncentiveData[]>
protocolAction: ProtocolAction.supply,
customMessage: antiLoopMessage,
},
{
action: MeritAction.CELO_SUPPLY_MULTIPLE_BORROW_USDT,
rewardTokenAddress: AaveV3Celo.ASSETS.CELO.A_TOKEN,
rewardTokenSymbol: 'aCelCELO',
protocolAction: ProtocolAction.supply,
customMessage: celoSupplyMultipleBorrowUsdtMessage,
},
{
action: MeritAction.CELO_BORROW_CELO,
rewardTokenAddress: AaveV3Celo.ASSETS.CELO.A_TOKEN,
Expand All @@ -595,6 +616,13 @@ const MERIT_DATA_MAP: Record<string, Record<string, MeritReserveIncentiveData[]>
protocolAction: ProtocolAction.borrow,
customMessage: antiLoopBorrowMessage,
},
{
action: MeritAction.CELO_SUPPLY_MULTIPLE_BORROW_USDT,
rewardTokenAddress: AaveV3Celo.ASSETS.CELO.A_TOKEN,
rewardTokenSymbol: 'aCelCELO',
protocolAction: ProtocolAction.borrow,
customMessage: celoSupplyMultipleBorrowUsdtMessage,
},
],
USDC: [
{
Expand All @@ -620,6 +648,13 @@ const MERIT_DATA_MAP: Record<string, Record<string, MeritReserveIncentiveData[]>
protocolAction: ProtocolAction.supply,
customMessage: antiLoopMessage,
},
{
action: MeritAction.CELO_SUPPLY_MULTIPLE_BORROW_USDT,
rewardTokenAddress: AaveV3Celo.ASSETS.CELO.A_TOKEN,
rewardTokenSymbol: 'aCelCELO',
protocolAction: ProtocolAction.supply,
customMessage: celoSupplyMultipleBorrowUsdtMessage,
},
{
action: MeritAction.CELO_BORROW_WETH,
rewardTokenAddress: AaveV3Celo.ASSETS.CELO.A_TOKEN,
Expand All @@ -644,6 +679,7 @@ export const useMeritIncentives = ({
queryFn: async () => {
const response = await fetch(url);
const data = await response.json();

const meritIncentives = data.currentAPR as MeritIncentives;

return meritIncentives;
Expand All @@ -655,27 +691,37 @@ export const useMeritIncentives = ({
if (!meritReserveIncentiveData) {
return null;
}
const incentive = meritReserveIncentiveData.find(

const incentives = meritReserveIncentiveData.filter(
(item) => item.protocolAction === protocolAction
);

if (!incentive) {
if (incentives.length === 0) {
return null;
}

const APR = data.actionsAPR[incentive.action];
let maxAPR = null;
let selectedIncentive = null;

for (const incentive of incentives) {
const APR = data.actionsAPR[incentive.action];
if (APR && (maxAPR === null || APR > maxAPR)) {
maxAPR = APR;
selectedIncentive = incentive;
}
}

if (!APR) {
if (!selectedIncentive || maxAPR === null) {
return null;
}

return {
incentiveAPR: (APR / 100).toString(),
rewardTokenAddress: incentive.rewardTokenAddress,
rewardTokenSymbol: incentive.rewardTokenSymbol,
action: incentive.action,
customMessage: incentive.customMessage,
customForumLink: incentive.customForumLink,
incentiveAPR: (maxAPR / 100).toString(),
rewardTokenAddress: selectedIncentive.rewardTokenAddress,
rewardTokenSymbol: selectedIncentive.rewardTokenSymbol,
action: selectedIncentive.action,
customMessage: selectedIncentive.customMessage,
customForumLink: selectedIncentive.customForumLink,
} as ExtendedReserveIncentiveResponse;
},
});
Expand Down
44 changes: 41 additions & 3 deletions src/hooks/useMerklIncentives.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,15 @@ type MerklOpportunity = {
};
};

export type ExtendedReserveIncentiveResponse = ReserveIncentiveResponse & {
customMessage: string;
customForumLink: string;
type ReserveIncentiveAdditionalData = {
customClaimMessage?: string;
customMessage?: string;
customForumLink?: string;
};

export type ExtendedReserveIncentiveResponse = ReserveIncentiveResponse &
ReserveIncentiveAdditionalData;

const allAaveAssets = [
AaveV3Ethereum.ASSETS,
AaveV3EthereumLido.ASSETS,
Expand All @@ -111,6 +115,28 @@ const allAaveAssets = [
AaveV3Soneium.ASSETS,
];

const additionalIncentiveData: Record<string, ReserveIncentiveAdditionalData> = {
[AaveV3Ethereum.ASSETS.USDe.A_TOKEN]: {
customMessage:
'You must supply USDe and hold an equal or greater amount of sUSDe (by USD value) to receive the incentives. To be eligible, your assets supplied must be at least 2x your account equity, and you must not be borrowing any USDe.',
},
[AaveV3Ethereum.ASSETS.USDtb.A_TOKEN]: {
customMessage:
'You must supply USDtb to receive incentives. To be eligible, you must not be borrowing any USDtb.',
customClaimMessage: 'Rewards will be claimable starting in early August.',
customForumLink: 'https://x.com/ethena_labs/status/1950194502192550149',
},
};

const hardcodedIncentives: Record<string, ExtendedReserveIncentiveResponse> = {
[AaveV3Ethereum.ASSETS.USDe.A_TOKEN]: {
incentiveAPR: '0.12',
rewardTokenAddress: AaveV3Ethereum.ASSETS.USDe.A_TOKEN,
rewardTokenSymbol: 'aEthUSDe',
...additionalIncentiveData[AaveV3Ethereum.ASSETS.USDe.A_TOKEN],
},
};

const getUnderlyingAndAToken = (assets: {
[key: string]: {
UNDERLYING: Address;
Expand All @@ -125,6 +151,7 @@ const getUnderlyingAndAToken = (assets: {

const otherTokensWhitelisted = [
'0x04eadd7b10ea9a484c60860aea7a7c0aec09b9f0', // aUSDtb wrapper contract
'0x3a4de44B29995a3D8Cd02d46243E1563E55bCc8b', // Aave Ethereum USDe (wrapped)
];

const whitelistedRewardTokens = [
Expand Down Expand Up @@ -166,6 +193,12 @@ export const useMerklIncentives = ({
queryKey: ['merklIncentives', market],
staleTime: 1000 * 60 * 5,
select: (merklOpportunities) => {
const hardcodedIncentive = rewardedAsset ? hardcodedIncentives[rewardedAsset] : undefined;

if (hardcodedIncentive) {
return hardcodedIncentive;
}

const opportunities = merklOpportunities.filter(
(opportunitiy) =>
rewardedAsset &&
Expand Down Expand Up @@ -197,10 +230,15 @@ export const useMerklIncentives = ({
return null;
}

const incentiveAdditionalData = rewardedAsset
? additionalIncentiveData[rewardedAsset]
: undefined;

return {
incentiveAPR: apr.toString(),
rewardTokenAddress: rewardToken.address,
rewardTokenSymbol: rewardToken.symbol,
...incentiveAdditionalData,
} as ExtendedReserveIncentiveResponse;
},
});
Expand Down
Loading
Loading