From c1314e7b8a06dc61da93c106e4f660e5e0a0cf1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Pr=C3=A9vost?= <998369+prevostc@users.noreply.github.com> Date: Sat, 23 Mar 2024 14:00:18 +0100 Subject: [PATCH] Add investor position level harvests amount --- schema.graphql | 26 ++++++++++++++++++++++---- src/entity/position.ts | 10 ++++++++++ src/harvest.ts | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/schema.graphql b/schema.graphql index f180996..4cda123 100644 --- a/schema.graphql +++ b/schema.graphql @@ -570,10 +570,8 @@ type Investor @entity { "The transactions count that the investor was the sender of" cumulativeInteractionsCount: Int! - "All deposits of the investor" cumulativeDepositCount: Int! - "All withdraws of the investor" cumulativeWithdrawCount: Int! @@ -621,10 +619,8 @@ type InvestorSnapshot implements Snapshot @entity { "Interactions count for the investor at the time of the snapshot" interactionsCount: Int! - "Deposits count for the investor at the time of the snapshot" depositCount: Int! - "Withdraws count for the investor at the time of the snapshot" withdrawCount: Int! @@ -674,6 +670,17 @@ type InvestorPosition @entity { "The last daily position values in USD for the last 30 days. Most recent last." last30DailyPositionValuesUSD: [BigDecimal!]! + "The harvested amount of the first token" + cumulativeHarvestedAmount0: BigDecimal! + "The harvested amount of the second token" + cumulativeHarvestedAmount1: BigDecimal! + "The harvested amount of the first token in USD" + cumulativeHarvestedAmount0USD: BigDecimal! + "The harvested amount of the second token in USD" + cumulativeHarvestedAmount1USD: BigDecimal! + "The harvested amount in USD" + cumulativeHarvestValueUSD: BigDecimal! + "All investor position snapshots" snapshots: [InvestorPositionSnapshot!]! @derivedFrom(field: "investorPosition") @@ -722,6 +729,17 @@ type InvestorPositionSnapshot implements Snapshot @entity { "Current position value in USD" positionValueUSD: BigDecimal! + + "The harvested amount of the first token at the time of the snapshot" + harvestedAmount0: BigDecimal! + "The harvested amount of the second token at the time of the snapshot" + harvestedAmount1: BigDecimal! + "The harvested amount of the first token in USD at the time of the snapshot" + harvestedAmount0USD: BigDecimal! + "The harvested amount of the second token in USD at the time of the snapshot" + harvestedAmount1USD: BigDecimal! + "The harvested amount in USD at the time of the snapshot" + harvestValueUSD: BigDecimal! } enum InvestorPositionInteractionType { diff --git a/src/entity/position.ts b/src/entity/position.ts index 1757c64..6c30f4c 100644 --- a/src/entity/position.ts +++ b/src/entity/position.ts @@ -33,6 +33,11 @@ export function getInvestorPosition(vault: BeefyCLVault, investor: Investor): In position.positionValueUSD = ZERO_BD position.averageDailyPositionValueUSD30D = ZERO_BD position.last30DailyPositionValuesUSD = new Array() + position.cumulativeHarvestedAmount0 = ZERO_BD + position.cumulativeHarvestedAmount1 = ZERO_BD + position.cumulativeHarvestedAmount0USD = ZERO_BD + position.cumulativeHarvestedAmount1USD = ZERO_BD + position.cumulativeHarvestValueUSD = ZERO_BD } return position } @@ -59,6 +64,11 @@ export function getInvestorPositionSnapshot( snapshot.underlyingBalance0USD = ZERO_BD snapshot.underlyingBalance1USD = ZERO_BD snapshot.positionValueUSD = ZERO_BD + snapshot.harvestedAmount0 = ZERO_BD + snapshot.harvestedAmount1 = ZERO_BD + snapshot.harvestedAmount0USD = ZERO_BD + snapshot.harvestedAmount1USD = ZERO_BD + snapshot.harvestValueUSD = ZERO_BD } // copy non-reseting values from the previous snapshot to the new snapshot diff --git a/src/harvest.ts b/src/harvest.ts index a6790fb..6cc3cf1 100644 --- a/src/harvest.ts +++ b/src/harvest.ts @@ -55,6 +55,14 @@ export function handleStrategyHarvest(event: HarvestEvent): void { const vaultBalanceUnderlying0 = tokenAmountToDecimal(vaultBalancesRes.value.value0, token0.decimals) const vaultBalanceUnderlying1 = tokenAmountToDecimal(vaultBalancesRes.value.value1, token1.decimals) + // vault shares total supply + const sharesTotalSupplyRes = vaultContract.try_totalSupply() + if (sharesTotalSupplyRes.reverted) { + log.error("handleStrategyHarvest: totalSupply() reverted for vault {}", [vault.id.toHexString()]) + throw Error("handleStrategyHarvest: totalSupply() reverted") + } + const sharesTotalSupply = tokenAmountToDecimal(sharesTotalSupplyRes.value, sharesToken.decimals) + // preview withdraw of 1 share token let previewWithdraw0Raw = BigInt.fromI32(0) let previewWithdraw1Raw = BigInt.fromI32(0) @@ -162,6 +170,8 @@ export function handleStrategyHarvest(event: HarvestEvent): void { } positivePositionCount += 1 + const positionPercentOfTotalSupply = position.sharesBalance.div(sharesTotalSupply) + log.debug("handleStrategyHarvest: updating investor position for investor {}", [position.investor.toHexString()]) let investor = getInvestor(position.investor) position.underlyingBalance0 = position.sharesBalance.times(shareTokenToUnderlying0Rate) @@ -171,6 +181,19 @@ export function handleStrategyHarvest(event: HarvestEvent): void { const previousPositionValueUSD = position.positionValueUSD position.positionValueUSD = position.underlyingBalance0USD.plus(position.underlyingBalance1USD) const positionChangeUSD = position.positionValueUSD.minus(previousPositionValueUSD) + position.cumulativeHarvestedAmount0 = position.cumulativeHarvestedAmount0.plus( + harvest.harvestedAmount0.times(positionPercentOfTotalSupply), + ) + position.cumulativeHarvestedAmount1 = position.cumulativeHarvestedAmount1.plus( + harvest.harvestedAmount1.times(positionPercentOfTotalSupply), + ) + position.cumulativeHarvestedAmount0USD = position.cumulativeHarvestedAmount0USD.plus( + harvest.harvestedAmount0USD.times(positionPercentOfTotalSupply), + ) + position.cumulativeHarvestedAmount1USD = position.cumulativeHarvestedAmount1USD.plus( + harvest.harvestedAmount1USD.times(positionPercentOfTotalSupply), + ) + position.cumulativeHarvestValueUSD = position.cumulativeHarvestValueUSD.plus(positionChangeUSD) position.save() for (let i = 0; i < periods.length; i++) { log.debug("handleStrategyHarvest: updating investor position snapshot for investor {} and period {}", [ @@ -184,6 +207,19 @@ export function handleStrategyHarvest(event: HarvestEvent): void { positionSnapshot.underlyingBalance0USD = position.underlyingBalance0USD positionSnapshot.underlyingBalance1USD = position.underlyingBalance1USD positionSnapshot.positionValueUSD = position.positionValueUSD + positionSnapshot.harvestedAmount0 = positionSnapshot.harvestedAmount0.plus( + harvest.harvestedAmount0.times(positionPercentOfTotalSupply), + ) + positionSnapshot.harvestedAmount1 = positionSnapshot.harvestedAmount1.plus( + harvest.harvestedAmount1.times(positionPercentOfTotalSupply), + ) + positionSnapshot.harvestedAmount0USD = positionSnapshot.harvestedAmount0USD.plus( + harvest.harvestedAmount0USD.times(positionPercentOfTotalSupply), + ) + positionSnapshot.harvestedAmount1USD = positionSnapshot.harvestedAmount1USD.plus( + harvest.harvestedAmount1USD.times(positionPercentOfTotalSupply), + ) + positionSnapshot.harvestValueUSD = positionSnapshot.harvestValueUSD.plus(positionChangeUSD) positionSnapshot.save() }