Skip to content

Commit 476bfd4

Browse files
committed
more detailed protocol stats
1 parent e031034 commit 476bfd4

File tree

8 files changed

+1338
-1261
lines changed

8 files changed

+1338
-1261
lines changed

db/migrations/1756731711034-Data.js renamed to db/migrations/1756936231004-Data.js

Lines changed: 489 additions & 489 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schema.graphql

Lines changed: 669 additions & 662 deletions
Large diffs are not rendered by default.

src/mainnet/processors/protocol/protocol.graphql

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ type ProtocolDailyStat @entity {
33
date: String! @index
44
timestamp: DateTime! @index
55
rateUSD: BigInt!
6-
earningTVL: BigInt!
6+
earningTvl: BigInt! # TVL of the product, including fees.
77
tvl: BigInt!
8-
revenue: BigInt!
8+
yield: BigInt! # Yield generated, including fees.
9+
revenue: BigInt! # Fees generated.
910
apy: Float!
1011
meta: JSON!
1112
}
@@ -16,8 +17,13 @@ type ProtocolDailyStatDetail @entity {
1617
product: String! @index
1718
timestamp: DateTime! @index
1819
rateUSD: BigInt!
19-
earningTVL: BigInt!
20+
earningTvl: BigInt!
2021
tvl: BigInt!
21-
revenue: BigInt!
22+
yield: BigInt! # Yield generated by the product, including fees.
23+
revenue: BigInt! # Fees generated by the product.
2224
apy: Float!
25+
inheritedTvl: BigInt! # TVL of the product that is inherited from another product.
26+
inheritedYield: BigInt! # Yield of the product that is inherited from another product.
27+
inheritedRevenue: BigInt! # Fees of the product that is inherited from another product.
28+
bridgedTvl: BigInt! # TVL of the product that is bridged from another product.
2329
}

src/mainnet/processors/protocol/protocol.ts

Lines changed: 89 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ import {
1919
} from '@originprotocol/squid-utils'
2020
import { getLatestExchangeRateForDate } from '@shared/post-processors/exchange-rates/exchange-rates'
2121
import { baseAddresses } from '@utils/addresses-base'
22-
import { armProducts, otokenProducts } from '@utils/products'
22+
import { plumeAddresses } from '@utils/addresses-plume'
23+
import { ProductName, armProducts, otokenProducts } from '@utils/products'
2324

2425
const startDate = '2022-01-01'
2526

@@ -54,53 +55,21 @@ export const protocolProcessor = defineProcessor({
5455
dailyStat.rateUSD = await getLatestExchangeRateForDate(ctx, 'ETH_USD', dailyStat.timestamp).then(
5556
(rate) => (rate?.rate ?? 0n) * 10n ** 10n,
5657
)
57-
dailyStat.earningTVL = sumBigIntBy(dateDetails, 'earningTVL')
58-
dailyStat.tvl = sumBigIntBy(dateDetails, 'tvl')
58+
dailyStat.earningTvl = sumBigIntBy(dateDetails, 'earningTvl')
59+
dailyStat.tvl = sumBigIntBy(dateDetails, 'tvl') - sumBigIntBy(dateDetails, 'inheritedTvl')
5960
dailyStat.revenue = sumBigIntBy(dateDetails, 'revenue')
61+
dailyStat.yield = sumBigIntBy(dateDetails, 'yield') + dailyStat.revenue
6062

61-
// Find overlapping TVL
62-
const superOETHbWrappedOETH = await ctx.store.findOne(StrategyBalance, {
63-
where: {
64-
strategy: baseAddresses.superOETHb.strategies.bridgedWOETH,
65-
timestamp: LessThanOrEqual(dayjs.utc(date).endOf('day').toDate()),
66-
},
67-
order: {
68-
timestamp: 'desc',
69-
},
70-
})
71-
const superOETHbWrappedOethBalance = superOETHbWrappedOETH?.balanceETH ?? 0n
72-
73-
// Adjust TVL for overlapping strategy balance.
74-
dailyStat.tvl -= superOETHbWrappedOethBalance
75-
dailyStat.apy =
76-
dailyStat.tvl === 0n
77-
? 0
78-
: dateDetails.reduce((acc, detail) => {
79-
// We lessen the OETH TVL for APY calculation since that APY is also included in Super OETHb.
80-
const tvl = detail.id === 'OETH' ? detail.tvl - superOETHbWrappedOethBalance : detail.tvl
81-
return acc + detail.apy * Number(tvl)
82-
}, 0) / Number(dailyStat.tvl)
83-
84-
dailyStat.meta = {
85-
tvlAdjustments: superOETHbWrappedOETH
86-
? [
87-
{
88-
name: 'Super OETHb Wrapped OETH Strategy',
89-
blockNumber: superOETHbWrappedOETH.blockNumber,
90-
timestamp: superOETHbWrappedOETH.timestamp,
91-
balanceETH: superOETHbWrappedOETH.balanceETH.toString(),
92-
},
93-
]
94-
: [],
95-
}
63+
const apyYield = dailyStat.yield - dailyStat.revenue
64+
dailyStat.apy = dailyStat.earningTvl !== 0n ? (Number(apyYield) / Number(dailyStat.earningTvl)) * 365 : 0
9665

9766
dailyStats.push(dailyStat)
9867
}
9968
await ctx.store.upsert(dailyStats)
10069
},
10170
})
10271

103-
const getLatestProtocolDailyStatDetail = async (ctx: Context, product: string) => {
72+
const getLatestProtocolDailyStatDetail = async (ctx: Context, product: ProductName) => {
10473
const latestProtocolDailyStatDetail = await ctx.store.findOne(ProtocolDailyStatDetail, {
10574
order: {
10675
date: 'desc',
@@ -126,10 +95,12 @@ const getProtocolDailyStat = async (ctx: Context, date: string) => {
12695
date,
12796
timestamp: dayjs.utc(date).endOf('day').toDate(),
12897
rateUSD: 0n,
129-
earningTVL: 0n,
98+
earningTvl: 0n,
13099
tvl: 0n,
100+
yield: 0n,
131101
revenue: 0n,
132102
apy: 0,
103+
meta: {},
133104
})
134105
}
135106
const getProtocolDailyStatDetail = async (ctx: Context, date: string, product: string) => {
@@ -146,10 +117,14 @@ const getProtocolDailyStatDetail = async (ctx: Context, date: string, product: s
146117
product,
147118
timestamp: dayjs.utc(date).endOf('day').toDate(),
148119
rateUSD: 0n,
149-
earningTVL: 0n,
120+
earningTvl: 0n,
150121
tvl: 0n,
122+
yield: 0n,
151123
revenue: 0n,
152124
apy: 0,
125+
inheritedTvl: 0n,
126+
inheritedYield: 0n,
127+
inheritedRevenue: 0n,
153128
})
154129
}
155130

@@ -161,16 +136,25 @@ const getOTokenDetails = async (
161136
otokenAddress,
162137
}: {
163138
processorId: string
164-
product: string
139+
product: ProductName
165140
otokenAddress: string
166141
},
167142
) => {
168143
const last = await getLatestProtocolDailyStatDetail(ctx, product)
144+
145+
// Since we depend on superOETHb and superOETHp, we need to continue updating
146+
// our product's details until our dependencies are all caught up.
147+
const lastSuperOETHb = await getLatestProtocolDailyStatDetail(ctx, 'superOETHb')
148+
const lastSuperOETHp = await getLatestProtocolDailyStatDetail(ctx, 'superOETHp')
149+
const lastDates = [last?.date, lastSuperOETHb?.date, lastSuperOETHp?.date].filter(Boolean) as string[]
150+
const oldestDate = lastDates.length > 0 ? lastDates.reduce((min, d) => (d < min ? d : min), lastDates[0]) : undefined
151+
169152
const status = await ctx.store.findOne(ProcessingStatus, { where: { id: processorId } })
170153
if (!status) return []
171154

172155
const details: ProtocolDailyStatDetail[] = []
173-
const dates = getDatesBetween(last?.date ?? startDate, getDateForTimestamp(status.timestamp.valueOf()))
156+
157+
const dates = getDatesBetween(oldestDate ?? startDate, getDateForTimestamp(status.timestamp.valueOf()))
174158
const dailyStats = await ctx.store.find(OTokenDailyStat, { where: { date: In(dates), otoken: otokenAddress } })
175159
for (const date of dates) {
176160
const otokenDailyStat = dailyStats.find((d) => d.date === date)
@@ -179,11 +163,64 @@ const getOTokenDetails = async (
179163
return details
180164
}
181165
const detail = await getProtocolDailyStatDetail(ctx, date, product)
166+
const eth = (value: bigint) => (value * otokenDailyStat.rateETH) / BigInt(10 ** 18)
182167
detail.rateUSD = otokenDailyStat.rateUSD
183-
detail.earningTVL = (otokenDailyStat.rebasingSupply * otokenDailyStat.rateETH) / BigInt(10 ** 18)
184-
detail.tvl = (otokenDailyStat.totalSupply * otokenDailyStat.rateETH) / BigInt(10 ** 18)
185-
detail.revenue = (otokenDailyStat.fees * otokenDailyStat.rateETH) / BigInt(10 ** 18)
168+
detail.earningTvl = eth(otokenDailyStat.rebasingSupply)
169+
detail.tvl = eth(otokenDailyStat.totalSupply)
170+
detail.yield = eth(otokenDailyStat.yield + otokenDailyStat.fees)
171+
detail.revenue = eth(otokenDailyStat.fees)
186172
detail.apy = otokenDailyStat.apy
173+
detail.inheritedTvl = 0n
174+
detail.inheritedYield = 0n
175+
detail.inheritedRevenue = 0n
176+
detail.bridgedTvl = 0n
177+
178+
const getLatestStrategyBalance = async (ctx: Context, strategy: string, date: string) => {
179+
return await ctx.store.findOne(StrategyBalance, {
180+
where: {
181+
strategy,
182+
timestamp: LessThanOrEqual(dayjs.utc(date).endOf('day').toDate()),
183+
},
184+
order: {
185+
timestamp: 'desc',
186+
},
187+
})
188+
}
189+
190+
if (detail.product === 'OETH') {
191+
// Pull superOETHp and superOETHb overlapping details.
192+
const superOETHbWrappedOETH = await getLatestStrategyBalance(
193+
ctx,
194+
baseAddresses.superOETHb.strategies.bridgedWOETH,
195+
date,
196+
)
197+
const superOETHpWrappedOETH = await getLatestStrategyBalance(
198+
ctx,
199+
plumeAddresses.superOETHp.strategies.bridgedWOETH,
200+
date,
201+
)
202+
203+
detail.inheritedTvl = (superOETHbWrappedOETH?.balanceETH ?? 0n) + (superOETHpWrappedOETH?.balanceETH ?? 0n)
204+
detail.inheritedYield = detail.earningTvl !== 0n ? (detail.yield * detail.inheritedTvl) / detail.earningTvl : 0n
205+
detail.inheritedRevenue =
206+
detail.earningTvl !== 0n ? (detail.revenue * detail.inheritedTvl) / detail.earningTvl : 0n
207+
detail.bridgedTvl = (superOETHbWrappedOETH?.balanceETH ?? 0n) + (superOETHpWrappedOETH?.balanceETH ?? 0n)
208+
} else if (detail.product === 'superOETHb') {
209+
const superOETHbWrappedOETH = await getLatestStrategyBalance(
210+
ctx,
211+
baseAddresses.superOETHb.strategies.bridgedWOETH,
212+
date,
213+
)
214+
detail.bridgedTvl = superOETHbWrappedOETH?.balanceETH ?? 0n
215+
} else if (detail.product === 'superOETHp') {
216+
const superOETHpWrappedOETH = await getLatestStrategyBalance(
217+
ctx,
218+
plumeAddresses.superOETHp.strategies.bridgedWOETH,
219+
date,
220+
)
221+
detail.bridgedTvl = superOETHpWrappedOETH?.balanceETH ?? 0n
222+
}
223+
187224
details.push(detail)
188225
}
189226
return details
@@ -196,7 +233,7 @@ const getArmDetails = async (
196233
armAddress,
197234
}: {
198235
processorId: string
199-
product: string
236+
product: ProductName
200237
armAddress: string
201238
},
202239
) => {
@@ -215,10 +252,14 @@ const getArmDetails = async (
215252
}
216253
const detail = await getProtocolDailyStatDetail(ctx, date, product)
217254
detail.rateUSD = BigInt(Math.round(armDailyStat.rateUSD * 1e18))
218-
detail.earningTVL = armDailyStat.totalSupply
255+
detail.earningTvl = armDailyStat.totalSupply
219256
detail.tvl = armDailyStat.totalSupply
257+
detail.yield = armDailyStat.yield + armDailyStat.fees
220258
detail.revenue = armDailyStat.fees
221259
detail.apy = armDailyStat.apy
260+
detail.inheritedTvl = 0n
261+
detail.inheritedYield = 0n
262+
detail.inheritedRevenue = 0n
222263
details.push(detail)
223264
}
224265
return details

src/model/generated/index.ts

Lines changed: 54 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,36 @@
1-
export * from "./ognDailyStat.model"
2-
export * from "./coinGeckoCoinData.model"
1+
export * from "./utilCache.model"
2+
export * from "./exchangeRate.model"
3+
export * from "./nativeBalance.model"
4+
export * from "./legacyStaker.model"
5+
export * from "./curvePool.model"
6+
export * from "./curvePoolBalance.model"
7+
export * from "./curvePoolRate.model"
38
export * from "./protocolDailyStat.model"
49
export * from "./protocolDailyStatDetail.model"
510
export * from "./beaconDepositEvent.model"
611
export * from "./beaconDepositPubkey.model"
712
export * from "./accountingConsensusRewards.model"
813
export * from "./executionRewardsCollected.model"
9-
export * from "./walletLabels.model"
10-
export * from "./curvePool.model"
11-
export * from "./curvePoolBalance.model"
12-
export * from "./curvePoolRate.model"
14+
export * from "./coinGeckoCoinData.model"
1315
export * from "./ognBuyback.model"
14-
export * from "./nativeBalance.model"
15-
export * from "./legacyStaker.model"
16+
export * from "./walletLabels.model"
17+
export * from "./ognDailyStat.model"
18+
export * from "./ogv.model"
19+
export * from "./ogvAddress.model"
20+
export * from "./ogvLockupTxLog.model"
21+
export * from "./_ogvLockupEventType"
22+
export * from "./ogvLockup.model"
23+
export * from "./ogvProposalTxLog.model"
24+
export * from "./_ogvProposalEvent"
25+
export * from "./ogvProposal.model"
26+
export * from "./_ogvProposalState"
27+
export * from "./ogvProposalVote.model"
28+
export * from "./_ogvVoteType"
29+
export * from "./ogvDailyStat.model"
30+
export * from "./transactionDetails.model"
31+
export * from "./pool.model"
32+
export * from "./poolBooster.model"
33+
export * from "./poolBoosterBribeExecuted.model"
1634
export * from "./oToken.model"
1735
export * from "./oTokenRawData.model"
1836
export * from "./woToken.model"
@@ -33,24 +51,43 @@ export * from "./oTokenHarvesterYieldSent.model"
3351
export * from "./oTokenRewardTokenCollected.model"
3452
export * from "./oTokenWithdrawalRequest.model"
3553
export * from "./oTokenYieldForwarded.model"
36-
export * from "./poolBooster.model"
37-
export * from "./poolBoosterBribeExecuted.model"
38-
export * from "./transactionDetails.model"
39-
export * from "./strategyBalance.model"
40-
export * from "./strategyYield.model"
41-
export * from "./strategyDailyYield.model"
4254
export * from "./arm.model"
4355
export * from "./armState.model"
4456
export * from "./armDailyStat.model"
4557
export * from "./armWithdrawalRequest.model"
4658
export * from "./armSwap.model"
4759
export * from "./traderateChanged.model"
60+
export * from "./erc20.model"
61+
export * from "./erc20Holder.model"
62+
export * from "./erc20State.model"
63+
export * from "./erc20StateByDay.model"
64+
export * from "./erc20Balance.model"
65+
export * from "./erc20Transfer.model"
66+
export * from "./processingStatus.model"
67+
export * from "./aeroClGaugeNotifyReward.model"
68+
export * from "./aeroGaugeNotifyReward.model"
69+
export * from "./aeroPoolCreated.model"
70+
export * from "./aeroClPoolCreated.model"
71+
export * from "./aeroVoterGaugeCreated.model"
72+
export * from "./aeroPoolState.model"
73+
export * from "./aeroClPoolState.model"
74+
export * from "./aeroClPoolTick.model"
75+
export * from "./aeroPoolEpochState.model"
76+
export * from "./_tokenAmount"
77+
export * from "./aeroLp.model"
78+
export * from "./aeroLpPosition.model"
4879
export * from "./governanceProposalEvent.model"
4980
export * from "./_governanceProposalEventType"
5081
export * from "./governanceProposal.model"
5182
export * from "./_governanceProposalState"
5283
export * from "./governanceProposalVote.model"
5384
export * from "./_governanceVoteType"
85+
export * from "./bridgeTransfer.model"
86+
export * from "./bridgeTransferState.model"
87+
export * from "./frrsRewardCollected.model"
88+
export * from "./frrsRewardsPerSecondChanged.model"
89+
export * from "./frrsRewardsTargetChange.model"
90+
export * from "./frrsStrategistUpdated.model"
5491
export * from "./esToken.model"
5592
export * from "./esAccount.model"
5693
export * from "./esYield.model"
@@ -64,46 +101,9 @@ export * from "./esPenalty.model"
64101
export * from "./esReward.model"
65102
export * from "./esStake.model"
66103
export * from "./esUnstake.model"
67-
export * from "./bridgeTransfer.model"
68-
export * from "./bridgeTransferState.model"
69-
export * from "./aeroPoolState.model"
70-
export * from "./aeroClPoolState.model"
71-
export * from "./aeroClPoolTick.model"
72-
export * from "./aeroPoolEpochState.model"
73-
export * from "./_tokenAmount"
74-
export * from "./aeroLp.model"
75-
export * from "./aeroLpPosition.model"
76-
export * from "./aeroClGaugeNotifyReward.model"
77-
export * from "./aeroGaugeNotifyReward.model"
78-
export * from "./aeroPoolCreated.model"
79-
export * from "./aeroClPoolCreated.model"
80-
export * from "./aeroVoterGaugeCreated.model"
81-
export * from "./frrsRewardCollected.model"
82-
export * from "./frrsRewardsPerSecondChanged.model"
83-
export * from "./frrsRewardsTargetChange.model"
84-
export * from "./frrsStrategistUpdated.model"
85-
export * from "./processingStatus.model"
86-
export * from "./erc20.model"
87-
export * from "./erc20Holder.model"
88-
export * from "./erc20State.model"
89-
export * from "./erc20StateByDay.model"
90-
export * from "./erc20Balance.model"
91-
export * from "./erc20Transfer.model"
92-
export * from "./pool.model"
104+
export * from "./strategyBalance.model"
105+
export * from "./strategyYield.model"
106+
export * from "./strategyDailyYield.model"
93107
export * from "./sfcWithdrawal.model"
94108
export * from "./morphoMarketState.model"
95109
export * from "./eventWoethPriceUpdated.model"
96-
export * from "./utilCache.model"
97-
export * from "./exchangeRate.model"
98-
export * from "./ogv.model"
99-
export * from "./ogvAddress.model"
100-
export * from "./ogvLockupTxLog.model"
101-
export * from "./_ogvLockupEventType"
102-
export * from "./ogvLockup.model"
103-
export * from "./ogvProposalTxLog.model"
104-
export * from "./_ogvProposalEvent"
105-
export * from "./ogvProposal.model"
106-
export * from "./_ogvProposalState"
107-
export * from "./ogvProposalVote.model"
108-
export * from "./_ogvVoteType"
109-
export * from "./ogvDailyStat.model"

0 commit comments

Comments
 (0)