Skip to content

Commit

Permalink
Faster ingestion: no receipt and less snapshots
Browse files Browse the repository at this point in the history
  • Loading branch information
prevostc committed Apr 20, 2024
1 parent 8572997 commit 95a55fb
Show file tree
Hide file tree
Showing 12 changed files with 86 additions and 201 deletions.
32 changes: 0 additions & 32 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ type Transaction @entity(immutable: true) {

"The address of the sender of the transaction"
sender: Bytes!

"Gas fee paid for the transaction in the native token"
gasFee: BigDecimal!
}

"""
Expand Down Expand Up @@ -164,30 +161,6 @@ type ProtocolSnapshot implements Snapshot @entity {
"Number of transactions initiated by harvesters at the time of the snapshot"
harvesterTransactionsCount: Int!

"Total amount of gas spent by anyone at the time of the snapshot"
totalGasSpent: BigDecimal!
"Total amount of gas spent by anyone in USD at the time of the snapshot"
totalGasSpentUSD: BigDecimal!
"Total amount of gas spent by investors at the time of the snapshot"
investorGasSpent: BigDecimal!
"Total amount of gas spent by investors in USD at the time of the snapshot"
investorGasSpentUSD: BigDecimal!
"Total amount of gas spent by harvesters at the time of the snapshot"
harvesterGasSpent: BigDecimal!
"Total amount of gas spent by harvesters in USD at the time of the snapshot"
harvesterGasSpentUSD: BigDecimal!

"""
Total amount of gas saved by the protocol at the time of the snapshot.
Each time an harvest transaction is executed, this value is increased by the amount of gas saved.
Gas saved is equal the the number of gas units that would have been spent if the transaction was executed on-chain
by each investor instead of using the Beefy Finance protocol.
It is expressed in native token.
"""
protocolGasSaved: BigDecimal!
"Total amount of gas saved by the protocol in USD at the time of the snapshot"
protocolGasSavedUSD: BigDecimal!

"Amount of fees collected by the protocol in the native token at the time of the snapshot"
protocolFeesCollectedNative: BigDecimal!
"Total amount of fees collected by the protocol in USD at the time of the snapshot"
Expand All @@ -202,11 +175,6 @@ type ProtocolSnapshot implements Snapshot @entity {
strategistFeesCollectedNative: BigDecimal!
"Total amount of strategist incentive fees collected by the protocol in USD at the time of the snapshot"
strategistFeesCollectedUSD: BigDecimal!

"Zap fees collected by the protocol in the native token at the time of the snapshot"
zapFeesCollectedNative: BigDecimal!
"Total amount of zap fees collected by the protocol in USD at the time of the snapshot"
zapFeesCollectedUSD: BigDecimal!
}

#############################
Expand Down
63 changes: 13 additions & 50 deletions src/boost-interaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,28 +21,18 @@ import { getTransaction } from "./entity/transaction"
import { ZERO_BD, tokenAmountToDecimal } from "./utils/decimal"
import { getToken } from "./entity/token"
import { getBeefyCLProtocol, getBeefyCLProtocolSnapshot } from "./entity/protocol"
import { SNAPSHOT_PERIODS } from "./utils/time"
import { fetchNativePriceUSD } from "./utils/price"
import { PROTOCOL_SNAPSHOT_PERIODS } from "./utils/time"

export function handleBoostStake(event: StakedEvent): void {
const tx = getTransaction(event.block, event.transaction, event.receipt)
const tx = getTransaction(event.block, event.transaction)
tx.save()

const periods = SNAPSHOT_PERIODS
const protocol = getBeefyCLProtocol()
const boost = getBoost(event.address)
const vault = getBeefyCLVault(boost.vault)
const investor = getInvestor(event.params.user)
const position = getInvestorPosition(vault, investor)

///////
// fetch native token price
const nativePriceUSD = fetchNativePriceUSD()

///////
// compute derived values
const txGasFeeUSD = tx.gasFee.times(nativePriceUSD)

/////
// create the interaction
let positionInteraction = getBoostInteraction(vault, investor, position, tx, event)
Expand All @@ -59,12 +49,9 @@ export function handleBoostStake(event: StakedEvent): void {
protocol.cumulativeTransactionCount += 1
protocol.cumulativeInvestorInteractionsCount += 1
protocol.save()
for (let i = 0; i < periods.length; i++) {
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, periods[i])
protocolSnapshot.totalGasSpent = protocolSnapshot.totalGasSpent.plus(tx.gasFee)
protocolSnapshot.totalGasSpentUSD = protocolSnapshot.totalGasSpentUSD.plus(txGasFeeUSD)
protocolSnapshot.investorGasSpent = protocolSnapshot.investorGasSpent.plus(tx.gasFee)
protocolSnapshot.investorGasSpentUSD = protocolSnapshot.investorGasSpentUSD.plus(txGasFeeUSD)
for (let i = 0; i < PROTOCOL_SNAPSHOT_PERIODS.length; i++) {
const period = PROTOCOL_SNAPSHOT_PERIODS[i]
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, period)
if (investor.lastInteractionAt.lt(protocolSnapshot.roundedTimestamp))
protocolSnapshot.uniqueActiveInvestorCount += 1
protocolSnapshot.transactionCount += 1
Expand All @@ -74,24 +61,15 @@ export function handleBoostStake(event: StakedEvent): void {
}

export function handleBoostWithdraw(event: WithdrawnEvent): void {
const tx = getTransaction(event.block, event.transaction, event.receipt)
const tx = getTransaction(event.block, event.transaction)
tx.save()

const periods = SNAPSHOT_PERIODS
const protocol = getBeefyCLProtocol()
const boost = getBoost(event.address)
const vault = getBeefyCLVault(boost.vault)
const investor = getInvestor(event.params.user)
const position = getInvestorPosition(vault, investor)

///////
// fetch native token price
const nativePriceUSD = fetchNativePriceUSD()

///////
// compute derived values
const txGasFeeUSD = tx.gasFee.times(nativePriceUSD)

/////
// create the interaction
let positionInteraction = getBoostInteraction(vault, investor, position, tx, event)
Expand All @@ -108,12 +86,9 @@ export function handleBoostWithdraw(event: WithdrawnEvent): void {
protocol.cumulativeTransactionCount += 1
protocol.cumulativeInvestorInteractionsCount += 1
protocol.save()
for (let i = 0; i < periods.length; i++) {
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, periods[i])
protocolSnapshot.totalGasSpent = protocolSnapshot.totalGasSpent.plus(tx.gasFee)
protocolSnapshot.totalGasSpentUSD = protocolSnapshot.totalGasSpentUSD.plus(txGasFeeUSD)
protocolSnapshot.investorGasSpent = protocolSnapshot.investorGasSpent.plus(tx.gasFee)
protocolSnapshot.investorGasSpentUSD = protocolSnapshot.investorGasSpentUSD.plus(txGasFeeUSD)
for (let i = 0; i < PROTOCOL_SNAPSHOT_PERIODS.length; i++) {
const period = PROTOCOL_SNAPSHOT_PERIODS[i]
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, period)
if (investor.lastInteractionAt.lt(protocolSnapshot.roundedTimestamp))
protocolSnapshot.uniqueActiveInvestorCount += 1
protocolSnapshot.transactionCount += 1
Expand All @@ -123,25 +98,16 @@ export function handleBoostWithdraw(event: WithdrawnEvent): void {
}

export function handleBoostReward(event: RewardPaidEvent): void {
const tx = getTransaction(event.block, event.transaction, event.receipt)
const tx = getTransaction(event.block, event.transaction)
tx.save()

const periods = SNAPSHOT_PERIODS
const protocol = getBeefyCLProtocol()
const boost = getBoost(event.address)
const vault = getBeefyCLVault(boost.vault)
const investor = getInvestor(event.params.user)
const position = getInvestorPosition(vault, investor)
const rewardToken = getToken(boost.rewardedIn)

///////
// fetch native token price
const nativePriceUSD = fetchNativePriceUSD()

///////
// compute derived values
const txGasFeeUSD = tx.gasFee.times(nativePriceUSD)

/////
// create the interaction
let positionInteraction = getBoostInteraction(vault, investor, position, tx, event)
Expand All @@ -158,12 +124,9 @@ export function handleBoostReward(event: RewardPaidEvent): void {
protocol.cumulativeTransactionCount += 1
protocol.cumulativeInvestorInteractionsCount += 1
protocol.save()
for (let i = 0; i < periods.length; i++) {
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, periods[i])
protocolSnapshot.totalGasSpent = protocolSnapshot.totalGasSpent.plus(tx.gasFee)
protocolSnapshot.totalGasSpentUSD = protocolSnapshot.totalGasSpentUSD.plus(txGasFeeUSD)
protocolSnapshot.investorGasSpent = protocolSnapshot.investorGasSpent.plus(tx.gasFee)
protocolSnapshot.investorGasSpentUSD = protocolSnapshot.investorGasSpentUSD.plus(txGasFeeUSD)
for (let i = 0; i < PROTOCOL_SNAPSHOT_PERIODS.length; i++) {
const period = PROTOCOL_SNAPSHOT_PERIODS[i]
const protocolSnapshot = getBeefyCLProtocolSnapshot(event.block.timestamp, period)
if (investor.lastInteractionAt.lt(protocolSnapshot.roundedTimestamp))
protocolSnapshot.uniqueActiveInvestorCount += 1
protocolSnapshot.transactionCount += 1
Expand Down
2 changes: 1 addition & 1 deletion src/boost-lifecycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { getBeefyCLVault, isNewVault } from "./entity/vault"
export function handleBoostCreated(event: BoostDeployedEvent): void {
const boostAddress = event.params.boost

const tx = getTransaction(event.block, event.transaction, event.receipt)
const tx = getTransaction(event.block, event.transaction)
tx.save()

const boostContract = BeefyBoostContract.bind(boostAddress)
Expand Down
29 changes: 14 additions & 15 deletions src/clock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { BigDecimal, BigInt, Bytes, ethereum, log } from "@graphprotocol/graph-ts"
import { ClockTick, Investor } from "../generated/schema"
import { DAY, MINUTES_15, SNAPSHOT_PERIODS } from "./utils/time"
import { DAY, HOUR, VAULT_SNAPSHOT_PERIODS, INVESTOR_SNAPSHOT_PERIODS, PROTOCOL_SNAPSHOT_PERIODS } from "./utils/time"
import { getClockTick } from "./entity/clock"
import { getBeefyCLProtocol, getBeefyCLProtocolSnapshot } from "./entity/protocol"
import { ZERO_BD } from "./utils/decimal"
Expand All @@ -14,21 +14,20 @@ import { DailyAvgCalc, DailyAvgState } from "./utils/daily-avg"
export function handleClockTick(block: ethereum.Block): void {
const timestamp = block.timestamp

let tickRes15min = getClockTick(timestamp, MINUTES_15)
if (!tickRes15min.isNew) {
log.debug("handleClockTick: tick already exists for 15 minutes period", [])
let tickRes1h = getClockTick(timestamp, HOUR)
if (!tickRes1h.isNew) {
log.debug("handleClockTick: tick already exists for 1h period", [])
return
}
tickRes15min.tick.save()
tickRes1h.tick.save()

let tickResDay = getClockTick(timestamp, DAY)
tickResDay.tick.save()

updateDataOnClockTick(tickRes15min.tick, tickResDay.isNew)
updateDataOnClockTick(tickRes1h.tick, tickResDay.isNew)
}

function updateDataOnClockTick(tick: ClockTick, isNewDay: boolean): void {
const periods = SNAPSHOT_PERIODS
const protocol = getBeefyCLProtocol()
let protocolTotalValueLockedUSD = ZERO_BD
let protocolActiveVaultCount = 0
Expand Down Expand Up @@ -78,8 +77,8 @@ function updateDataOnClockTick(tick: ClockTick, isNewDay: boolean): void {
vault.totalValueLockedUSD = vault.underlyingAmount0USD.plus(vault.underlyingAmount1USD)
vault.save()
// update vault snapshots
for (let j = 0; j < periods.length; j++) {
const period = periods[j]
for (let j = 0; j < VAULT_SNAPSHOT_PERIODS.length; j++) {
const period = VAULT_SNAPSHOT_PERIODS[j]
const vaultSnapshot = getBeefyCLVaultSnapshot(vault, tick.timestamp, period)
vaultSnapshot.currentPriceOfToken0InToken1 = vault.currentPriceOfToken0InToken1
vaultSnapshot.currentPriceOfToken0InUSD = vault.currentPriceOfToken0InUSD
Expand Down Expand Up @@ -122,8 +121,8 @@ function updateDataOnClockTick(tick: ClockTick, isNewDay: boolean): void {
position.averageDailyPositionValueUSDState = state.serialize()
position.save()
// update position snapshot
for (let k = 0; k < periods.length; k++) {
const period = periods[k]
for (let k = 0; k < INVESTOR_SNAPSHOT_PERIODS.length; k++) {
const period = INVESTOR_SNAPSHOT_PERIODS[k]
const positionSnapshot = getInvestorPositionSnapshot(vault, investor, tick.timestamp, period)
positionSnapshot.underlyingBalance0USD = position.underlyingBalance0USD
positionSnapshot.underlyingBalance1USD = position.underlyingBalance1USD
Expand Down Expand Up @@ -171,8 +170,8 @@ function updateDataOnClockTick(tick: ClockTick, isNewDay: boolean): void {
state,
).serialize()
investor.save()
for (let j = 0; j < periods.length; j++) {
const period = periods[j]
for (let j = 0; j < INVESTOR_SNAPSHOT_PERIODS.length; j++) {
const period = INVESTOR_SNAPSHOT_PERIODS[j]
const investorSnapshot = getInvestorSnapshot(investor, tick.timestamp, period)
investorSnapshot.totalPositionValueUSD = tvl
investorSnapshot.save()
Expand All @@ -185,8 +184,8 @@ function updateDataOnClockTick(tick: ClockTick, isNewDay: boolean): void {
protocol.activeVaultCount = protocolActiveVaultCount
protocol.activeInvestorCount = protocolActiveInvestorCount
protocol.save()
for (let i = 0; i < periods.length; i++) {
const period = periods[i]
for (let i = 0; i < PROTOCOL_SNAPSHOT_PERIODS.length; i++) {
const period = PROTOCOL_SNAPSHOT_PERIODS[i]
const protocolSnapshot = getBeefyCLProtocolSnapshot(tick.timestamp, period)
protocolSnapshot.totalValueLockedUSD = protocol.totalValueLockedUSD
protocolSnapshot.activeVaultCount = protocol.activeVaultCount
Expand Down
8 changes: 0 additions & 8 deletions src/entity/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,6 @@ export function getBeefyCLProtocolSnapshot(timestamp: BigInt, period: BigInt): P
snapshot.transactionCount = 0
snapshot.investorInteractionsCount = 0
snapshot.harvesterTransactionsCount = 0
snapshot.totalGasSpent = ZERO_BD
snapshot.totalGasSpentUSD = ZERO_BD
snapshot.investorGasSpent = ZERO_BD
snapshot.investorGasSpentUSD = ZERO_BD
snapshot.harvesterGasSpent = ZERO_BD
snapshot.harvesterGasSpentUSD = ZERO_BD
snapshot.protocolGasSaved = ZERO_BD
snapshot.protocolGasSavedUSD = ZERO_BD
snapshot.protocolFeesCollectedNative = ZERO_BD
snapshot.protocolFeesCollectedUSD = ZERO_BD
snapshot.harvesterFeesCollectedNative = ZERO_BD
Expand Down
12 changes: 1 addition & 11 deletions src/entity/transaction.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { ethereum, log } from "@graphprotocol/graph-ts"
import { ethereum } from "@graphprotocol/graph-ts"
import { Transaction } from "../../generated/schema"
import { weiToBigDecimal } from "../utils/decimal"
import { ADDRESS_ZERO } from "../utils/address"

export function getTransaction(
block: ethereum.Block,
transaction: ethereum.Transaction,
receipt: ethereum.TransactionReceipt | null,
): Transaction {
let transactionId = transaction.hash
let tx = Transaction.load(transactionId)
Expand All @@ -15,14 +13,6 @@ export function getTransaction(
tx.blockNumber = block.number
tx.blockTimestamp = block.timestamp
tx.sender = transaction.from || ADDRESS_ZERO
if (!receipt) {
log.warning(
'No receipt for transaction {}. Set "receipt: true" on the event handler configuration in subgraph.yaml',
[transactionId.toHexString()],
)
throw Error('No receipt. Set "receipt: true" on the event handler configuration in subgraph.yaml')
}
tx.gasFee = weiToBigDecimal(transaction.gasPrice.times(receipt.gasUsed))
}
return tx
}
5 changes: 3 additions & 2 deletions src/utils/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ export const WEEK = BigInt.fromI32(60 * 60 * 24 * 7)
export const MONTH = BigInt.fromI32(60 * 60 * 24 * 30)
export const QUARTER = BigInt.fromI32(60 * 60 * 24 * 30 * 3)
export const YEAR = BigInt.fromI32(60 * 60 * 24 * 365)
export const SNAPSHOT_PERIODS = [HOUR, DAY, WEEK, MONTH, QUARTER, YEAR]

export const PROTOCOL_SNAPSHOT_PERIODS = [DAY, MONTH, QUARTER, YEAR]
export const VAULT_SNAPSHOT_PERIODS = [HOUR, DAY, MONTH]
export const INVESTOR_SNAPSHOT_PERIODS = [HOUR, DAY, MONTH]

@inline
export function getIntervalFromTimestamp(timestamp: BigInt, period: BigInt): BigInt {
Expand Down
Loading

0 comments on commit 95a55fb

Please sign in to comment.