1+ import { Stake } from '@aave/contract-helpers' ;
2+ import { valueToBigNumber } from '@aave/math-utils' ;
13import { AaveSafetyModule } from '@bgd-labs/aave-address-book' ;
24import { Trans } from '@lingui/macro' ;
35import { Box , Stack , Typography , useMediaQuery , useTheme } from '@mui/material' ;
4- import { useEffect } from 'react' ;
6+ import NumberFlow from '@number-flow/react' ;
7+ import { BigNumber } from 'bignumber.js' ;
8+ import { formatEther } from 'ethers/lib/utils' ;
9+ import { useEffect , useState } from 'react' ;
510import { FormattedNumber } from 'src/components/primitives/FormattedNumber' ;
611import { TokenIcon } from 'src/components/primitives/TokenIcon' ;
12+ import { TextWithTooltip } from 'src/components/TextWithTooltip' ;
713import { TopInfoPanel } from 'src/components/TopInfoPanel/TopInfoPanel' ;
814import { useAppDataContext } from 'src/hooks/app-data-provider/useAppDataProvider' ;
915import { StakeTokenFormatted , useGeneralStakeUiData } from 'src/hooks/stake/useGeneralStakeUiData' ;
16+ import { useUserStakeUiData } from 'src/hooks/stake/useUserStakeUiData' ;
1017import { useStakeTokenAPR } from 'src/hooks/useStakeTokenAPR' ;
1118import { useWeb3Context } from 'src/libs/hooks/useWeb3Context' ;
1219import { useRootStore } from 'src/store/root' ;
@@ -68,7 +75,10 @@ export const SGHOHeader: React.FC = () => {
6875 < Trans >
6976 Deposit GHO into savings GHO (sGHO) and earn{ ' ' }
7077 < Box component = "span" sx = { { color : '#338E3C' , fontWeight : 'bold' } } >
71- { ( ( stakeAPR ?. apr ? convertAprToApy ( parseFloat ( stakeAPR . apr ) ) : 0 ) * 100 ) . toFixed ( 2 ) }
78+ { (
79+ ( stakeAPR ?. apr ? convertAprToApy ( new BigNumber ( stakeAPR . apr ) . toNumber ( ) ) : 0 ) *
80+ 100
81+ ) . toFixed ( 2 ) }
7282 %
7383 </ Box > { ' ' }
7484 APY on your GHO holdings. There's no lockups, no rehypothecation, and you can
@@ -90,6 +100,7 @@ export const SGHOHeader: React.FC = () => {
90100} ;
91101
92102const SGhoHeaderUserDetails = ( {
103+ currentMarketData,
93104 valueTypographyVariant,
94105 symbolsTypographyVariant,
95106 stkGho,
@@ -100,6 +111,7 @@ const SGhoHeaderUserDetails = ({
100111 stkGho : StakeTokenFormatted ;
101112} ) => {
102113 const { data : stakeAPR , isLoading : isLoadingStakeAPR } = useStakeTokenAPR ( ) ;
114+ const { data : stakeUserResult } = useUserStakeUiData ( currentMarketData , Stake . gho ) ;
103115 const { reserves } = useAppDataContext ( ) ;
104116
105117 const {
@@ -114,13 +126,33 @@ const SGhoHeaderUserDetails = ({
114126
115127 const downToSM = useMediaQuery ( theme . breakpoints . down ( 'sm' ) ) ;
116128
129+ const stakeUserData = stakeUserResult ?. [ 0 ] ;
130+ const userSGhoBalance = stakeUserData ?. stakeTokenRedeemableAmount || '0' ;
131+ const userSGhoBalanceFormatted = formatEther ( userSGhoBalance ) ;
132+
133+ // Calculate estimated weekly rewards with precision
134+ // Formula: (balance * APR) / 52 weeks
135+ const aprBN = stakeAPR ?. apr ? new BigNumber ( stakeAPR . apr ) : new BigNumber ( 0 ) ;
136+ const balanceBN = new BigNumber ( userSGhoBalanceFormatted || '0' ) ;
137+ const weeklyRewardsEstimateBN = balanceBN . multipliedBy ( aprBN ) . dividedBy ( 52 ) ;
138+ const weeklyRewardsEstimate = weeklyRewardsEstimateBN . toNumber ( ) ;
139+
140+ const [ displayedWeeklyRewards , setDisplayedWeeklyRewards ] = useState ( 0 ) ;
141+
142+ const symbolsColor = theme . palette . text . muted ;
143+ const iconSize = valueTypographyVariant === 'main21' ? 20 : 16 ;
144+
145+ useEffect ( ( ) => {
146+ setDisplayedWeeklyRewards ( Math . max ( 0 , weeklyRewardsEstimate ) ) ;
147+ } , [ weeklyRewardsEstimate ] ) ;
148+
117149 return (
118150 < >
119151 < TopInfoPanelItem hideIcon title = { < Trans > APY</ Trans > } loading = { isLoadingStakeAPR } >
120152 < FormattedNumber
121- value = { stakeAPR ?. apr ? convertAprToApy ( parseFloat ( stakeAPR . apr ) ) : 0 }
153+ value = { stakeAPR ?. apr ? convertAprToApy ( valueToBigNumber ( stakeAPR . apr ) . toNumber ( ) ) : 0 }
122154 variant = { valueTypographyVariant }
123- symbolsColor = "#A5A8B6"
155+ symbolsColor = { symbolsColor }
124156 visibleDecimals = { 2 }
125157 percent
126158 symbolsVariant = { symbolsTypographyVariant }
@@ -140,7 +172,7 @@ const SGhoHeaderUserDetails = ({
140172 symbol = "USD"
141173 variant = { valueTypographyVariant }
142174 symbolsVariant = { symbolsTypographyVariant }
143- symbolsColor = "#A5A8B6"
175+ symbolsColor = { symbolsColor }
144176 visibleDecimals = { 2 }
145177 />
146178 </ TopInfoPanelItem >
@@ -158,11 +190,77 @@ const SGhoHeaderUserDetails = ({
158190 symbol = "USD"
159191 variant = { valueTypographyVariant }
160192 symbolsVariant = { symbolsTypographyVariant }
161- symbolsColor = "#A5A8B6"
193+ symbolsColor = { symbolsColor }
162194 visibleDecimals = { 2 }
163195 />
164196 </ TopInfoPanelItem >
165197
198+ < TopInfoPanelItem
199+ hideIcon
200+ title = {
201+ < Stack direction = "row" alignItems = "center" >
202+ < TextWithTooltip text = { < Trans > Weekly Rewards</ Trans > } variant = "inherit" >
203+ < Trans >
204+ Estimated weekly rewards based on your current sGHO balance and APR. Actual rewards
205+ may vary depending on market conditions.
206+ </ Trans >
207+ </ TextWithTooltip >
208+ </ Stack >
209+ }
210+ loading = { isLoadingStakeAPR }
211+ >
212+ { balanceBN . gt ( 0 ) ? (
213+ < Typography
214+ variant = { valueTypographyVariant }
215+ sx = { {
216+ display : 'inline-flex' ,
217+ flexDirection : 'row' ,
218+ alignItems : 'center' ,
219+ position : 'relative' ,
220+ '& number-flow-react.custom-number-flow' : {
221+ '--number-flow-mask-height' : '0' ,
222+ '--number-flow-char-height' : '1em' ,
223+ fontVariantNumeric : 'tabular-nums' ,
224+ display : 'inline-block' ,
225+ verticalAlign : 'baseline' ,
226+ paddingLeft : '12px' ,
227+ paddingRight : '12px' ,
228+ paddingTop : '2px' ,
229+ } ,
230+ } }
231+ noWrap
232+ >
233+ < NumberFlow
234+ value = { displayedWeeklyRewards }
235+ format = { {
236+ minimumFractionDigits : 2 ,
237+ maximumFractionDigits : 2 ,
238+ } }
239+ style = { {
240+ color : 'inherit' ,
241+ fontFamily : 'inherit' ,
242+ fontSize : 'inherit' ,
243+ fontWeight : 'inherit' ,
244+ lineHeight : 'inherit' ,
245+ } }
246+ className = "custom-number-flow"
247+ />
248+ < TokenIcon
249+ symbol = "sgho"
250+ sx = { {
251+ ml : 0.5 ,
252+ width : iconSize ,
253+ height : iconSize ,
254+ } }
255+ />
256+ </ Typography >
257+ ) : (
258+ < Typography variant = { valueTypographyVariant } color = { symbolsColor } >
259+ —
260+ </ Typography >
261+ ) }
262+ </ TopInfoPanelItem >
263+
166264 < Box sx = { { display : 'inline-flex' , alignItems : 'center' , height : '40px' } } >
167265 { poolReserve && (
168266 < >
0 commit comments