Skip to content

Commit 319e91e

Browse files
committed
using reward balance from the subgraph, which automatically udpates after rebase
1 parent f76eba6 commit 319e91e

File tree

7 files changed

+49
-143
lines changed

7 files changed

+49
-143
lines changed

frontend/src/components/GeyserFirst/GeyserStats.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,14 @@ import { DAY_IN_SEC, TOTAL_REWARDS_MSG } from '../../constants'
1010

1111
export const GeyserStats = () => {
1212
const {
13-
geyserStats: { duration, totalDeposit, totalRewards },
13+
geyserStats: { duration, totalDepositVal, totalRewards, totalRewardsVal },
1414
} = useContext(StatsContext)
1515
const {
1616
selectedGeyserInfo: {
17-
rewardTokenInfo: { symbol: rewardTokenSymbol, price: rewardTokenPrice },
17+
rewardTokenInfo: { symbol: rewardTokenSymbol },
1818
},
1919
} = useContext(GeyserContext)
2020

21-
const baseRewards = totalRewards * rewardTokenPrice
22-
2321
return (
2422
<GeyserStatsContainer>
2523
<Header>Geyser Stats</Header>
@@ -34,7 +32,7 @@ export const GeyserStats = () => {
3432
<GeyserStatsBoxContainer>
3533
<GeyserStatsBox
3634
name="Total Deposits"
37-
value={totalDeposit}
35+
value={totalDepositVal}
3836
units="USD"
3937
interpolate={(val) => safeNumeral(val, '0,0')}
4038
/>
@@ -43,7 +41,7 @@ export const GeyserStats = () => {
4341
<GeyserStatsBox
4442
containerClassName="w-full"
4543
name="Total Rewards"
46-
value={baseRewards}
44+
value={totalRewardsVal}
4745
units="USD"
4846
interpolate={(val) => safeNumeral(val, '0,0')}
4947
tooltipMessage={{
@@ -55,12 +53,12 @@ export const GeyserStats = () => {
5553
rows={[
5654
{
5755
label: `${rewardTokenSymbol} (${safeNumeral(totalRewards, '0,0')})`,
58-
value: `${safeNumeral(baseRewards, '0,0.00')} USD`,
56+
value: `${safeNumeral(totalRewardsVal, '0,0.00')} USD`,
5957
},
6058
{ label: 'bonus (0)', value: `${safeNumeral(0, '0,0.00')} USD` },
6159
]}
6260
totalLabel="Total"
63-
totalValue={`${safeNumeral(baseRewards, '0,0.00')} USD`}
61+
totalValue={`${safeNumeral(totalRewardsVal, '0,0.00')} USD`}
6462
/>
6563
</div>
6664
),

frontend/src/components/GeyserFirst/MyStats.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export const MyStats = () => {
4242
setFinalAPY(Math.min(geyserAPYNew + lpAPYNew, 100000))
4343
}, [selectedGeyser, apy])
4444

45-
// NOTE: removed bonus tokens
45+
// TODO: handle bonus tokens
4646
const baseRewards = currentReward * rewardTokenPrice
4747
return (
4848
<MyStatsContainer>

frontend/src/components/GeyserFirst/UnstakeSummary.tsx

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,15 @@ export const UnstakeSummary: React.FC<Props> = ({ userInput, parsedUserInput })
2020
stakingTokenInfo: { symbol: stakingTokenSymbol, price: stakingTokenPrice },
2121
},
2222
} = useContext(GeyserContext)
23-
const {
24-
geyserStats: { bonusRewards },
25-
computeRewardsFromUnstake,
26-
computeRewardsShareFromUnstake,
27-
} = useContext(StatsContext)
23+
const { computeRewardsFromUnstake, computeRewardsShareFromUnstake } = useContext(StatsContext)
2824

2925
const [rewardAmount, setRewardAmount] = useState<number>(0.0)
30-
const [rewardsShare, setRewardsShare] = useState<number>(0.0)
26+
// const [rewardsShare, setRewardsShare] = useState<number>(0.0)
3127

3228
const unstakeUSD = parseFloat(userInput) * stakingTokenPrice
33-
const rewardUSD = rewardAmount * rewardTokenPrice + bonusRewards.reduce((m, b) => m + rewardsShare * b.value, 0)
34-
29+
const rewardUSD = rewardAmount * rewardTokenPrice
30+
// TODO: handle bonus rewards
31+
// bonusRewards.reduce((m, b) => m + rewardsShare * b.value, 0)
3532
useEffect(() => {
3633
let isMounted = true
3734
;(async () => {
@@ -78,12 +75,12 @@ export const UnstakeSummary: React.FC<Props> = ({ userInput, parsedUserInput })
7875
<span>{rewardTokenSymbol}</span>
7976
</Value>
8077

81-
{bonusRewards.map((b) => (
78+
{/* {bonusRewards.map((b) => (
8279
<Value key={b.symbol}>
8380
<Amount>{safeNumeral(rewardsShare * b.balance, '0.000')} </Amount>
8481
<span>{b.symbol}</span>
8582
</Value>
86-
))}
83+
))} */}
8784
</Content>
8885
</SummaryCard>
8986
</Container>

frontend/src/components/Home.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,14 @@ import { Loader } from 'styling/styles'
1010
import { toChecksumAddress } from 'web3-utils'
1111
import TokenIcons from 'components/TokenIcons'
1212
import { safeNumeral } from 'utils/numeral'
13-
import { getGeyserTotalDeposit } from 'utils/stats'
14-
import { formatUnits } from 'ethers/lib/utils'
13+
import { getGeyserTotalDeposit, getGeyserTotalRewards } from 'utils/stats'
1514
import { getPlatformConfig } from 'config/app'
1615

17-
const nowInSeconds = () => Math.round(Date.now() / 1000)
18-
1916
export const Home = () => {
2017
const { geysers, getGeyserConfig, allTokensInfos, stakeAPYs } = useContext(GeyserContext)
2118
const { selectedVault } = useContext(VaultContext)
2219
const navigate = useNavigate()
2320
const stakedGeysers = selectedVault ? selectedVault.locks.map((l) => l.geyser) : []
24-
const now = nowInSeconds()
2521
const tokensByAddress = allTokensInfos.reduce((acc, t) => {
2622
acc[toChecksumAddress(t.address)] = t
2723
return acc
@@ -39,16 +35,7 @@ export const Home = () => {
3935
const apy = lpAPY + geyserAPY
4036
const programName = extractProgramName(config.name)
4137
const platform = getPlatformConfig(config)
42-
43-
let rewards = 0
44-
if (rewardTokenInfo) {
45-
// NOTE: This math doesn't work if AMPL is the reward token as it doesn't account for rebasing!
46-
const rewardAmt = g.rewardSchedules
47-
.filter((s) => parseInt(s.start, 10) + parseInt(s.duration, 10) > now)
48-
.reduce((m, s) => m + parseFloat(formatUnits(s.rewardAmount, rewardTokenInfo.decimals)), 0)
49-
rewards = rewardAmt * rewardTokenInfo.price
50-
}
51-
38+
const rewards = rewardTokenInfo ? getGeyserTotalRewards(g, rewardTokenInfo) : 0
5239
const isStablePool = config.name.includes('USDC') && config.name.includes('SPOT')
5340
const poolType = `${isStablePool ? 'Stable' : 'Vol'}[${stakingTokens.join('/')}]`
5441
return {

frontend/src/types.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ export type StakingTokenInfo = TokenInfo & {
8888

8989
export type RewardTokenInfo = TokenInfo & {
9090
price: number
91-
getTotalRewards: (rewardSchedules: RewardSchedule[]) => Promise<number>
9291
}
9392

9493
export type BonusTokenInfo = TokenInfo & {
@@ -114,10 +113,13 @@ export type RewardStats = {
114113
export type GeyserStats = {
115114
duration: number
116115
totalDeposit: number
116+
totalDepositVal: number
117117
totalRewards: number
118+
totalRewardVal: number
118119
calcPeriodInDays: number
119120
unlockedRewards: number
120121
bonusRewards: RewardStats[]
122+
bonusRewardsVal: number
121123
}
122124

123125
export type VaultTokenBalance = TokenInfo & {

frontend/src/utils/rewardToken.ts

Lines changed: 6 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,14 @@
1-
import { Contract } from 'ethers'
2-
import { formatUnits } from 'ethers/lib/utils'
31
import { RewardToken, MIN_IN_MS } from '../constants'
4-
import { RewardSchedule, RewardTokenInfo, SignerOrProvider } from '../types'
5-
import { UFRAGMENTS_ABI } from './abis/UFragments'
6-
import { UFRAGMENTS_POLICY_ABI } from './abis/UFragmentsPolicy'
7-
import { XC_AMPLE_ABI } from './abis/XCAmple'
8-
import { XC_CONTROLLER_ABI } from './abis/XCController'
9-
import { computeAMPLRewardShares } from './ampleforth'
2+
import { RewardTokenInfo, SignerOrProvider } from '../types'
103
import { defaultTokenInfo, getTokenInfo } from './token'
114
import { getCurrentPrice } from './price'
125
import * as ls from './cache'
136

147
const cacheTimeMs = 30 * MIN_IN_MS
158

16-
const nowInSeconds = () => Math.round(Date.now() / 1000)
17-
function filterActiveRewardSchedules(rewardSchedules) {
18-
const now = nowInSeconds()
19-
return rewardSchedules.filter((s) => parseInt(s.start, 10) + parseInt(s.duration, 10) > now)
20-
}
21-
229
export const defaultRewardTokenInfo = (): RewardTokenInfo => ({
2310
...defaultTokenInfo(),
2411
price: 1,
25-
getTotalRewards: async () => 0,
2612
})
2713

2814
export const getRewardTokenInfo = async (
@@ -36,7 +22,7 @@ export const getRewardTokenInfo = async (
3622
case RewardToken.AMPL:
3723
return getAMPLToken(tokenAddress, signerOrProvider)
3824
case RewardToken.XCAMPLE:
39-
return getXCAMPLToken(tokenAddress, signerOrProvider)
25+
return getAMPLToken(tokenAddress, signerOrProvider)
4026
case RewardToken.WAMPL:
4127
return getBasicToken(tokenAddress, signerOrProvider)
4228
case RewardToken.SPOT:
@@ -48,8 +34,8 @@ export const getRewardTokenInfo = async (
4834
}
4935
}
5036

51-
const getBasicToken = async (tokenAddress: string, signerOrProvider: SignerOrProvider): Promise<RewardTokenInfo> => {
52-
const rewardTokenInfo = await ls.computeAndCache<RewardTokenInfo>(
37+
const getBasicToken = async (tokenAddress: string, signerOrProvider: SignerOrProvider): Promise<RewardTokenInfo> =>
38+
ls.computeAndCache<RewardTokenInfo>(
5339
async function () {
5440
const tokenInfo = await getTokenInfo(tokenAddress, signerOrProvider)
5541
const price = await getCurrentPrice(tokenInfo.symbol)
@@ -58,95 +44,14 @@ const getBasicToken = async (tokenAddress: string, signerOrProvider: SignerOrPro
5844
`rewardTokenInfo:${tokenAddress}`,
5945
cacheTimeMs,
6046
)
61-
rewardTokenInfo.getTotalRewards = async (rewardSchedules: RewardSchedule[]) =>
62-
filterActiveRewardSchedules(rewardSchedules).reduce(
63-
(acc, schedule) => acc + parseFloat(formatUnits(schedule.rewardAmount, 0)),
64-
0,
65-
)
66-
return rewardTokenInfo
67-
}
68-
69-
// TODO: use subgraph to get AMPL supply history
70-
const getAMPLToken = async (tokenAddress: string, signerOrProvider: SignerOrProvider): Promise<RewardTokenInfo> => {
71-
const rewardTokenInfo = await ls.computeAndCache<RewardTokenInfo>(
72-
async function () {
73-
const tokenInfo = await getTokenInfo(tokenAddress, signerOrProvider)
74-
const price = await getCurrentPrice('AMPL')
75-
return { price, ...tokenInfo }
76-
},
77-
`rewardTokenInfo:${tokenAddress}`,
78-
cacheTimeMs,
79-
)
80-
81-
rewardTokenInfo.amplInfo = await ls.computeAndCache<any>(
82-
async function () {
83-
const contract = new Contract(tokenAddress, UFRAGMENTS_ABI, signerOrProvider)
84-
const policyAddress: string = await contract.monetaryPolicy()
85-
const policy = new Contract(policyAddress, UFRAGMENTS_POLICY_ABI, signerOrProvider)
86-
const totalSupply = await contract.totalSupply()
87-
const epoch = await policy.epoch()
88-
return { policyAddress, epoch, totalSupply }
89-
},
90-
`amplRewardTokenInfo:${tokenAddress}`,
91-
cacheTimeMs,
92-
)
93-
94-
rewardTokenInfo.getTotalRewards = async (rewardSchedules: RewardSchedule[]) => {
95-
const tokenInfo = rewardTokenInfo
96-
const ampl = rewardTokenInfo.amplInfo
97-
const totalRewardShares = await computeAMPLRewardShares(
98-
filterActiveRewardSchedules(rewardSchedules),
99-
tokenAddress,
100-
ampl.policyAddress,
101-
false,
102-
parseInt(ampl.epoch, 10),
103-
tokenInfo.decimals,
104-
signerOrProvider,
105-
)
106-
return totalRewardShares * formatUnits(ampl.totalSupply, tokenInfo.decimals)
107-
}
108-
109-
return rewardTokenInfo
110-
}
11147

112-
const getXCAMPLToken = async (tokenAddress: string, signerOrProvider: SignerOrProvider): Promise<RewardTokenInfo> => {
113-
const rewardTokenInfo = await ls.computeAndCache<RewardTokenInfo>(
48+
const getAMPLToken = async (tokenAddress: string, signerOrProvider: SignerOrProvider): Promise<RewardTokenInfo> =>
49+
ls.computeAndCache<RewardTokenInfo>(
11450
async function () {
11551
const tokenInfo = await getTokenInfo(tokenAddress, signerOrProvider)
11652
const price = await getCurrentPrice('AMPL')
11753
return { price, ...tokenInfo }
11854
},
11955
`rewardTokenInfo:${tokenAddress}`,
120-
0,
121-
)
122-
123-
rewardTokenInfo.amplInfo = await ls.computeAndCache<any>(
124-
async function () {
125-
const token = new Contract(tokenAddress, XC_AMPLE_ABI, signerOrProvider)
126-
const controllerAddress: string = await token.controller()
127-
const controller = new Contract(controllerAddress, XC_CONTROLLER_ABI, signerOrProvider)
128-
const totalSupply = await token.globalAMPLSupply()
129-
const epoch = await controller.globalAmpleforthEpoch()
130-
return { epoch, totalSupply }
131-
},
132-
`xcAmplRewardTokenInfo:${tokenAddress}`,
13356
cacheTimeMs,
13457
)
135-
136-
rewardTokenInfo.getTotalRewards = async (rewardSchedules: RewardSchedule[]) => {
137-
const tokenInfo = rewardTokenInfo
138-
const ampl = rewardTokenInfo.amplInfo
139-
const totalRewardShares = await computeAMPLRewardShares(
140-
filterActiveRewardSchedules(rewardSchedules),
141-
tokenAddress,
142-
controllerAddress,
143-
true,
144-
parseInt(ampl.epoch, 10),
145-
tokenInfo.decimals,
146-
signerOrProvider,
147-
)
148-
return totalRewardShares * formatUnits(ampl.totalSupply, tokenInfo.decimals)
149-
}
150-
151-
return rewardTokenInfo
152-
}

frontend/src/utils/stats.ts

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ export const defaultUserStats = (): UserStats => ({
3636
export const defaultGeyserStats = (): GeyserStats => ({
3737
duration: 0,
3838
totalDeposit: 0,
39+
totalDepositVal: 0,
3940
totalRewards: 0,
41+
totalRewardsVal: 0,
4042
calcPeriodInDays: 0,
4143
unlockedRewards: 0,
4244
bonusRewards: [],
45+
bonusRewardsVal: 0,
4346
})
4447

4548
export const defaultVaultStats = (): VaultStats => ({
@@ -74,6 +77,13 @@ export const getGeyserTotalDeposit = (geyser: Geyser, stakingTokenInfo: StakingT
7477
return stakingTokenAmount * stakingTokenInfo.price
7578
}
7679

80+
export const getGeyserTotalRewards = (geyser: Geyser, rewardTokenInfo: RewardTokenInfo) => {
81+
const { rewardBalance } = geyser
82+
const { decimals } = rewardTokenInfo
83+
const rewardAmt = parseFloat(formatUnits(rewardBalance, decimals))
84+
return rewardAmt * rewardTokenInfo.price
85+
}
86+
7787
export const getGeyserStats = async (
7888
geyser: Geyser,
7989
stakingTokenInfo: StakingTokenInfo,
@@ -83,16 +93,17 @@ export const getGeyserStats = async (
8393
ls.computeAndCache<GeyserStats>(
8494
async () => ({
8595
duration: getGeyserDuration(geyser),
86-
totalDeposit: getGeyserTotalDeposit(geyser, stakingTokenInfo),
87-
totalRewards:
88-
(await rewardTokenInfo.getTotalRewards(geyser.rewardSchedules)) / 10 ** (rewardTokenInfo.decimals || 1),
8996
calcPeriodInDays: getCalcPeriod(geyser) / DAY_IN_SEC,
90-
unlockedRewards: parseFloat(geyser.unlockedReward) / 10 ** (rewardTokenInfo.decimals || 1),
97+
totalDeposit: parseFloat(formatUnits(geyser.totalStake, stakingTokenInfo.decimals)),
98+
totalDepositVal: getGeyserTotalDeposit(geyser, stakingTokenInfo),
99+
totalRewards: parseFloat(formatUnits(geyser.rewardBalance, rewardTokenInfo.decimals)),
100+
totalRewardsVal: getGeyserTotalRewards(geyser, rewardTokenInfo),
101+
unlockedRewards: parseFloat(formatUnits(geyser.unlockedReward, rewardTokenInfo.decimals)),
91102
bonusRewards:
92103
geyser.rewardPoolBalances.length === bonusTokensInfo.length
93104
? geyser.rewardPoolBalances.map((b, i) => {
94105
const info = bonusTokensInfo[i]
95-
const balance = parseFloat(b.balance) / 10 ** info.decimals
106+
const balance = parseFloat(formatUnits(b.balance, info.decimals))
96107
return {
97108
name: info.name,
98109
symbol: info.symbol,
@@ -101,6 +112,14 @@ export const getGeyserStats = async (
101112
}
102113
})
103114
: [],
115+
bonusRewardsVal:
116+
geyser.rewardPoolBalances.length === bonusTokensInfo.length
117+
? geyser.rewardPoolBalances.reduce((m, b, i) => {
118+
const info = bonusTokensInfo[i]
119+
const balance = parseFloat(formatUnits(b.balance, info.decimals))
120+
return m + info.price * balance
121+
}, 0)
122+
: 0,
104123
}),
105124
`${toChecksumAddress(geyser.id)}|stats`,
106125
statsCacheTimeMs,
@@ -234,8 +253,6 @@ export const getUserAPY = async (
234253

235254
const rewardPool = parseFloat(geyser.rewardBalance) / 10 ** rewardTokenDecimals
236255
const rewardShare = outflowReward / rewardPool
237-
238-
// TODO: data layer should guarantee that rewardPoolBalances and bonusTokensInfo are inline
239256
const outflowWithBonus =
240257
outflow +
241258
geyser.rewardPoolBalances.reduce((m, b, i) => {

0 commit comments

Comments
 (0)