From 02f14932ad8b9e89d1a8b63c20e2e1f72228289b Mon Sep 17 00:00:00 2001 From: Soil King <157099073+soilking@users.noreply.github.com> Date: Thu, 4 Apr 2024 18:08:53 -0700 Subject: [PATCH] Move block handler to its own datasource --- projects/subgraph-bean/src/BeanWellHandler.ts | 75 +------------------ projects/subgraph-bean/src/BlockHandler.ts | 63 ++++++++++++++++ projects/subgraph-bean/subgraph.yaml | 26 ++++++- projects/subgraph-bean/tests/Cross.test.ts | 2 +- 4 files changed, 92 insertions(+), 74 deletions(-) create mode 100644 projects/subgraph-bean/src/BlockHandler.ts diff --git a/projects/subgraph-bean/src/BeanWellHandler.ts b/projects/subgraph-bean/src/BeanWellHandler.ts index d64300f44b..4658b50a61 100644 --- a/projects/subgraph-bean/src/BeanWellHandler.ts +++ b/projects/subgraph-bean/src/BeanWellHandler.ts @@ -1,12 +1,11 @@ -import { Address, BigDecimal, BigInt, ethereum, log } from "@graphprotocol/graph-ts"; -import { BEANSTALK_PRICE, BEANSTALK_PRICE_BLOCK, BEAN_ERC20 } from "../../subgraph-core/utils/Constants"; +import { Address, BigDecimal, BigInt } from "@graphprotocol/graph-ts"; +import { BEANSTALK_PRICE, BEAN_ERC20 } from "../../subgraph-core/utils/Constants"; import { ZERO_BD, ZERO_BI, deltaBigIntArray, toDecimal } from "../../subgraph-core/utils/Decimals"; import { BeanstalkPrice } from "../generated/BeanWETHCP2w/BeanstalkPrice"; import { AddLiquidity, RemoveLiquidity, RemoveLiquidityOneToken, Shift, Swap, Sync } from "../generated/BeanWETHCP2w/Well"; import { loadBean, updateBeanSupplyPegPercent, updateBeanValues } from "./utils/Bean"; import { getPoolLiquidityUSD, loadOrCreatePool, setPoolReserves, updatePoolPrice, updatePoolValues } from "./utils/Pool"; -import { checkBeanCross, checkPoolCross } from "./utils/Cross"; -import { BEAN_WELLS, WellFunction } from "./utils/BeanWells"; +import { checkBeanCross } from "./utils/Cross"; export function handleAddLiquidity(event: AddLiquidity): void { handleLiquidityChange( @@ -75,74 +74,6 @@ export function handleShift(event: Shift): void { ); } -export function handleBlock(block: ethereum.Block): void { - // BeanstalkPrice contract was not deployed until about 20 mins after the first Well's deployment. - // In practice no data is lost by discarding these blocks, and the same is done elsewhere. - if (block.number.lt(BEANSTALK_PRICE_BLOCK)) { - return; - } - - const beanstalkPrice = BeanstalkPrice.bind(BEANSTALK_PRICE); - const beanPrice = beanstalkPrice.try_price(); - const bean = loadBean(BEAN_ERC20.toHexString()); - const prevPrice = bean.price; - const newPrice = toDecimal(beanPrice.value.price); - - log.debug("Prev/New bean price {} / {}", [prevPrice.toString(), newPrice.toString()]); - - // Check for overall peg cross - const beanCrossed = checkBeanCross(BEAN_ERC20.toHexString(), block.timestamp, block.number, prevPrice, newPrice); - - // Update pool price for each pool - necessary for checking pool cross - let totalLiquidity = ZERO_BD; - for (let i = 0; i < BEAN_WELLS.length; ++i) { - const wellInfo = BEAN_WELLS[i]; - if (block.number.lt(wellInfo.startBlock)) { - continue; - } - - const well = loadOrCreatePool(wellInfo.address.toHexString(), block.number); - - // Currently there is only one Well function, this needs to be expanded as more Bean wells are added. - // wellInfo.wellFunction == WellFunction.ConstantProduct ? ... - const newWellPrice = beanstalkPrice.try_getConstantProductWell(wellInfo.address).value; - const poolCrossed = checkPoolCross( - wellInfo.address.toHexString(), - block.timestamp, - block.number, - well.lastPrice, - toDecimal(newWellPrice.price) - ); - - if (poolCrossed || beanCrossed) { - totalLiquidity = totalLiquidity.plus(toDecimal(newWellPrice.liquidity)); - updatePoolValues( - wellInfo.address.toHexString(), - block.timestamp, - block.number, - ZERO_BI, - ZERO_BD, - toDecimal(newWellPrice.liquidity).minus(well.liquidityUSD), - newWellPrice.deltaB - ); - updatePoolPrice(wellInfo.address.toHexString(), block.timestamp, block.number, toDecimal(newWellPrice.price), false); - } - } - - // Update bean values at the end now that the summation of pool liquidity is known - if (beanCrossed) { - updateBeanValues( - BEAN_ERC20.toHexString(), - block.timestamp, - newPrice, - ZERO_BI, - ZERO_BI, - ZERO_BD, - totalLiquidity.minus(bean.liquidityUSD) - ); - } -} - function handleLiquidityChange( poolAddress: string, timestamp: BigInt, diff --git a/projects/subgraph-bean/src/BlockHandler.ts b/projects/subgraph-bean/src/BlockHandler.ts new file mode 100644 index 0000000000..22c01288a6 --- /dev/null +++ b/projects/subgraph-bean/src/BlockHandler.ts @@ -0,0 +1,63 @@ +import { ethereum, log } from "@graphprotocol/graph-ts"; +import { BEANSTALK_PRICE, BEAN_ERC20 } from "../../subgraph-core/utils/Constants"; +import { ZERO_BD, ZERO_BI, toDecimal } from "../../subgraph-core/utils/Decimals"; +import { BeanstalkPrice } from "../generated/BeanWETHCP2w/BeanstalkPrice"; +import { loadBean, updateBeanValues } from "./utils/Bean"; +import { loadOrCreatePool, updatePoolPrice, updatePoolValues } from "./utils/Pool"; +import { checkBeanCross, checkPoolCross } from "./utils/Cross"; + +// Processing as each new ethereum block is created +export function handleBlock(block: ethereum.Block): void { + const beanstalkPrice = BeanstalkPrice.bind(BEANSTALK_PRICE); + const priceResult = beanstalkPrice.try_price(); + const bean = loadBean(BEAN_ERC20.toHexString()); + const prevPrice = bean.price; + const newPrice = toDecimal(priceResult.value.price); + + log.debug("Prev/New bean price {} / {}", [prevPrice.toString(), newPrice.toString()]); + + // Check for overall peg cross + const beanCrossed = checkBeanCross(BEAN_ERC20.toHexString(), block.timestamp, block.number, prevPrice, newPrice); + + // Update pool price for each pool - necessary for checking pool cross + let totalLiquidity = ZERO_BD; + for (let i = 0; i < priceResult.value.ps.length; ++i) { + const poolPriceInfo = priceResult.value.ps[i]; + const pool = loadOrCreatePool(poolPriceInfo.pool.toHexString(), block.number); + + const poolCrossed = checkPoolCross( + poolPriceInfo.pool.toHexString(), + block.timestamp, + block.number, + pool.lastPrice, + toDecimal(poolPriceInfo.price) + ); + + if (poolCrossed || beanCrossed) { + totalLiquidity = totalLiquidity.plus(toDecimal(poolPriceInfo.liquidity)); + updatePoolValues( + poolPriceInfo.pool.toHexString(), + block.timestamp, + block.number, + ZERO_BI, + ZERO_BD, + toDecimal(poolPriceInfo.liquidity).minus(pool.liquidityUSD), + poolPriceInfo.deltaB + ); + updatePoolPrice(poolPriceInfo.pool.toHexString(), block.timestamp, block.number, toDecimal(poolPriceInfo.price), false); + } + } + + // Update bean values at the end now that the summation of pool liquidity is known + if (beanCrossed) { + updateBeanValues( + BEAN_ERC20.toHexString(), + block.timestamp, + newPrice, + ZERO_BI, + ZERO_BI, + ZERO_BD, + totalLiquidity.minus(bean.liquidityUSD) + ); + } +} diff --git a/projects/subgraph-bean/subgraph.yaml b/projects/subgraph-bean/subgraph.yaml index 97ccd92df1..8074b22f3c 100644 --- a/projects/subgraph-bean/subgraph.yaml +++ b/projects/subgraph-bean/subgraph.yaml @@ -238,6 +238,30 @@ dataSources: handler: handleShift - event: Sync(uint256[],uint256,address) handler: handleSync + file: ./src/BeanWellHandler.ts + - kind: ethereum/contract + name: BlockHandler + network: mainnet + source: + address: "0xb01CE0008CaD90104651d6A84b6B11e182a9B62A" + abi: BeanstalkPrice + startBlock: 17978222 + mapping: + kind: ethereum/events + apiVersion: 0.0.7 + language: wasm/assemblyscript + entities: + - Bean + - BeanHourlySnapshot + - BeanDailySnapshot + - BeanCross + - PoolCross + - Pool + - PoolHourlySnapshot + - PoolDailySnapshot + abis: + - name: BeanstalkPrice + file: ../subgraph-core/abis/BeanstalkPrice.json blockHandlers: - handler: handleBlock - file: ./src/BeanWellHandler.ts + file: ./src/BlockHandler.ts diff --git a/projects/subgraph-bean/tests/Cross.test.ts b/projects/subgraph-bean/tests/Cross.test.ts index 17b4bb1c5c..f4742c2592 100644 --- a/projects/subgraph-bean/tests/Cross.test.ts +++ b/projects/subgraph-bean/tests/Cross.test.ts @@ -2,7 +2,7 @@ import { beforeEach, afterEach, assert, clearStore, describe, test } from "match import { log } from "matchstick-as/assembly/log"; import { BigInt } from "@graphprotocol/graph-ts"; -import { handleBlock } from "../src/BeanWellHandler"; +import { handleBlock } from "../src/BlockHandler"; import { mockBlock } from "../../subgraph-core/tests/event-mocking/Block"; import { setMockBeanPrice } from "../../subgraph-core/tests/event-mocking/Price";