-
Notifications
You must be signed in to change notification settings - Fork 383
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨ Implement ZkSync Ignite incentives program #2305
Merged
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
e2cd27a
feat: put the merit button directly in the IncentivesCard
MartinGbz 441e67e
feat: implement ZkSync Ignite program
MartinGbz 57e689b
feat: add protocol action additional check
MartinGbz 05bc793
fix: remove logs
MartinGbz 7d49865
fix: api url
MartinGbz 9635329
fix: condition in IncentivesCard
MartinGbz 897fa47
fix: add market as queryKey
NandyBa e6a1350
fix: claim link
MartinGbz f2dad18
fix: rename asset for rewardedAsset
MartinGbz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
src/components/incentives/ZkSyncIgniteIncentivesTooltipContent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { Trans } from '@lingui/macro'; | ||
import { Box, Typography } from '@mui/material'; | ||
import { ExtendedReserveIncentiveResponse } from 'src/hooks/useMeritIncentives'; | ||
|
||
import { FormattedNumber } from '../primitives/FormattedNumber'; | ||
import { Link } from '../primitives/Link'; | ||
import { Row } from '../primitives/Row'; | ||
import { TokenIcon } from '../primitives/TokenIcon'; | ||
import { getSymbolMap } from './IncentivesTooltipContent'; | ||
|
||
export const ZkSyncIgniteIncentivesTooltipContent = ({ | ||
zkSyncIgniteIncentives, | ||
}: { | ||
zkSyncIgniteIncentives: ExtendedReserveIncentiveResponse; | ||
}) => { | ||
const typographyVariant = 'secondary12'; | ||
|
||
const zkSyncIgniteIncentivesFormatted = getSymbolMap(zkSyncIgniteIncentives); | ||
|
||
return ( | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
justifyContent: 'center', | ||
alignItems: 'start', | ||
flexDirection: 'column', | ||
}} | ||
> | ||
<img src={`/icons/other/zksync-ignite.svg`} width="100px" height="40px" alt="" /> | ||
|
||
<Typography variant="caption" color="text.primary" mb={3}> | ||
<Trans>Eligible for the ZKSync Ignite program.</Trans> | ||
</Typography> | ||
|
||
<Typography variant="caption" color="text.secondary" mb={3}> | ||
<Trans> | ||
This is a program initiated and implemented by the decentralised ZKSync community. Aave | ||
Labs does not guarantee the program and accepts no liability. | ||
</Trans>{' '} | ||
<Link | ||
href={'https://zksyncignite.xyz/'} | ||
sx={{ textDecoration: 'underline' }} | ||
variant="caption" | ||
color="text.secondary" | ||
> | ||
Learn more | ||
</Link> | ||
</Typography> | ||
|
||
<Typography variant="caption" color="text.secondary" mb={3}> | ||
<Trans>ZKSync Ignite Program rewards are claimed through the</Trans>{' '} | ||
<Link | ||
href="https://app.zksyncignite.xyz/" | ||
sx={{ textDecoration: 'underline' }} | ||
variant="caption" | ||
color="text.secondary" | ||
> | ||
official app | ||
</Link> | ||
{'.'} | ||
</Typography> | ||
{zkSyncIgniteIncentives.customMessage ? ( | ||
<Typography variant="caption" color="text.strong" mb={3}> | ||
<Trans>{zkSyncIgniteIncentives.customMessage}</Trans> | ||
</Typography> | ||
) : null} | ||
|
||
<Box sx={{ width: '100%' }}> | ||
<Row | ||
height={32} | ||
caption={ | ||
<Box | ||
sx={{ | ||
display: 'flex', | ||
alignItems: 'center', | ||
mb: 0, | ||
}} | ||
> | ||
<TokenIcon | ||
aToken={zkSyncIgniteIncentivesFormatted.aToken} | ||
symbol={zkSyncIgniteIncentivesFormatted.tokenIconSymbol} | ||
sx={{ fontSize: '20px', mr: 1 }} | ||
/> | ||
<Typography variant={typographyVariant}> | ||
{zkSyncIgniteIncentivesFormatted.symbol} | ||
</Typography> | ||
</Box> | ||
} | ||
width="100%" | ||
> | ||
<Box sx={{ display: 'inline-flex', alignItems: 'center' }}> | ||
<FormattedNumber | ||
value={+zkSyncIgniteIncentivesFormatted.incentiveAPR} | ||
percent | ||
variant={typographyVariant} | ||
/> | ||
<Typography variant={typographyVariant} sx={{ ml: 1 }}> | ||
<Trans>APR</Trans> | ||
</Typography> | ||
</Box> | ||
</Row> | ||
</Box> | ||
</Box> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { ProtocolAction } from '@aave/contract-helpers'; | ||
import { ReserveIncentiveResponse } from '@aave/math-utils/dist/esm/formatters/incentive/calculate-reserve-incentives'; | ||
import { AaveV3ZkSync } from '@bgd-labs/aave-address-book'; | ||
import { useQuery } from '@tanstack/react-query'; | ||
import { Address } from 'viem'; | ||
|
||
enum OpportunityAction { | ||
LEND = 'LEND', | ||
BORROW = 'BORROW', | ||
} | ||
|
||
enum OpportunityStatus { | ||
LIVE = 'LIVE', | ||
PAST = 'PAST', | ||
UPCOMING = 'UPCOMING', | ||
} | ||
|
||
type MerklOpportunity = { | ||
chainId: number; | ||
type: string; | ||
identifier: Address; | ||
name: string; | ||
status: OpportunityStatus; | ||
action: OpportunityAction; | ||
tvl: number; | ||
apr: number; | ||
dailyRewards: number; | ||
tags: []; | ||
id: string; | ||
tokens: [ | ||
{ | ||
id: string; | ||
name: string; | ||
chainId: number; | ||
address: Address; | ||
decimals: number; | ||
icon: string; | ||
verified: boolean; | ||
isTest: boolean; | ||
price: number; | ||
symbol: string; | ||
} | ||
]; | ||
}; | ||
|
||
export type ExtendedReserveIncentiveResponse = ReserveIncentiveResponse & { | ||
customMessage: string; | ||
customForumLink: string; | ||
}; | ||
|
||
const url = 'https://api.merkl.xyz/v4/opportunities?tags=zksync&mainProtocolId=aave'; // Merkl API for ZK Ignite opportunities | ||
|
||
const rewardToken = AaveV3ZkSync.ASSETS.ZK.UNDERLYING; | ||
const rewardTokenSymbol = 'ZK'; | ||
|
||
const checkOpportunityAction = ( | ||
opportunityAction: OpportunityAction, | ||
protocolAction: ProtocolAction | ||
) => { | ||
switch (opportunityAction) { | ||
case OpportunityAction.LEND: | ||
return protocolAction === ProtocolAction.supply; | ||
case OpportunityAction.BORROW: | ||
return protocolAction === ProtocolAction.borrow; | ||
default: | ||
return false; | ||
} | ||
}; | ||
|
||
export const useZkSyncIgniteIncentives = ({ | ||
asset, | ||
protocolAction, | ||
}: { | ||
asset?: string; | ||
protocolAction?: ProtocolAction; | ||
}) => { | ||
return useQuery({ | ||
queryFn: async () => { | ||
const response = await fetch(url); | ||
const merklOpportunities: MerklOpportunity[] = await response.json(); | ||
return merklOpportunities; | ||
}, | ||
queryKey: ['zkIgniteIncentives'], | ||
staleTime: 1000 * 60 * 5, | ||
select: (merklOpportunities) => { | ||
const opportunities = merklOpportunities.filter( | ||
(opportunitiy) => | ||
asset && | ||
opportunitiy.identifier.toLowerCase() === asset.toLowerCase() && | ||
protocolAction && | ||
checkOpportunityAction(opportunitiy.action, protocolAction) | ||
); | ||
|
||
if (opportunities.length === 0) { | ||
return null; | ||
} | ||
|
||
const opportunity = opportunities[0]; | ||
|
||
if (opportunity.status !== OpportunityStatus.LIVE) { | ||
return null; | ||
} | ||
|
||
const apr = opportunity.apr / 100; | ||
|
||
return { | ||
incentiveAPR: apr.toString(), | ||
rewardTokenAddress: rewardToken, | ||
rewardTokenSymbol: rewardTokenSymbol, | ||
} as ExtendedReserveIncentiveResponse; | ||
}, | ||
}); | ||
}; |
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see we are passing the term asset around. Can we make it more explicit like rewardAsset or something similar. This way its easier to understand when we are passing this variable @MartinGbz
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree with you
Asset here can be the aToken or the vToken (aave asset in any cases). If it was the underlying asset I would set it for
underlyingAsset
.I can set it to
rewardedAsset
what do you think?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed a commit: f2dad18