From b37b491a4686aa2447bf725d11813ab4efa778df Mon Sep 17 00:00:00 2001 From: Michael Wang <44713145+mzywang@users.noreply.github.com> Date: Fri, 12 Apr 2024 09:16:10 -0400 Subject: [PATCH] add collectHandler (#214) * split core handlers * remove yarn codegen from CI * update export * fix(lint): auto-fix [ci] * add collect event handler * remove double count * remove burn * remove burn * add comment * add linear ticket * remove unused comment * lint * update transaction ids to use log index * fix(lint): auto-fix [ci] --------- Co-authored-by: mzywang --- .prettierrc | 5 -- package.json | 5 ++ src/mappings/pool/burn.ts | 24 ++------- src/mappings/pool/collect.ts | 101 +++++++++++++++++++++++++++++++++++ src/mappings/pool/index.ts | 3 +- src/mappings/pool/mint.ts | 2 +- src/mappings/pool/swap.ts | 2 +- subgraph.yaml | 2 + 8 files changed, 117 insertions(+), 27 deletions(-) delete mode 100644 .prettierrc create mode 100644 src/mappings/pool/collect.ts diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 31ba22d8..00000000 --- a/.prettierrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "semi": false, - "singleQuote": true, - "printWidth": 120 -} diff --git a/package.json b/package.json index 975967ca..14867ded 100644 --- a/package.json +++ b/package.json @@ -27,5 +27,10 @@ "npm-run-all": "^4.1.5", "prettier": "^1.18.2", "typescript": "^3.5.2" + }, + "prettier": { + "printWidth": 120, + "semi": false, + "singleQuote": true } } diff --git a/src/mappings/pool/burn.ts b/src/mappings/pool/burn.ts index ccd2b391..0f2b2354 100644 --- a/src/mappings/pool/burn.ts +++ b/src/mappings/pool/burn.ts @@ -12,6 +12,7 @@ import { updateUniswapDayData, } from '../../utils/intervalUpdates' +// Note: this handler need not adjust TVL because that is accounted for in the handleCollect handler export function handleBurn(event: BurnEvent): void { const bundle = Bundle.load('1')! const poolAddress = event.address.toHexString() @@ -29,21 +30,14 @@ export function handleBurn(event: BurnEvent): void { .times(token0.derivedETH.times(bundle.ethPriceUSD)) .plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD))) - // reset tvl aggregates until new amounts calculated - factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH) - // update globals factory.txCount = factory.txCount.plus(ONE_BI) // update token0 data token0.txCount = token0.txCount.plus(ONE_BI) - token0.totalValueLocked = token0.totalValueLocked.minus(amount0) - token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD)) // update token1 data token1.txCount = token1.txCount.plus(ONE_BI) - token1.totalValueLocked = token1.totalValueLocked.minus(amount1) - token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD)) // pool data pool.txCount = pool.txCount.plus(ONE_BI) @@ -54,23 +48,15 @@ export function handleBurn(event: BurnEvent): void { BigInt.fromI32(event.params.tickLower).le(pool.tick as BigInt) && BigInt.fromI32(event.params.tickUpper).gt(pool.tick as BigInt) ) { + // todo: this liquidity can be calculated from the real reserves and + // current price instead of incrementally from every burned amount which + // may not be accurate: https://linear.app/uniswap/issue/DAT-336/fix-pool-liquidity pool.liquidity = pool.liquidity.minus(event.params.amount) } - pool.totalValueLockedToken0 = pool.totalValueLockedToken0.minus(amount0) - pool.totalValueLockedToken1 = pool.totalValueLockedToken1.minus(amount1) - pool.totalValueLockedETH = pool.totalValueLockedToken0 - .times(token0.derivedETH) - .plus(pool.totalValueLockedToken1.times(token1.derivedETH)) - pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD) - - // reset aggregates with new amounts - factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH) - factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) - // burn entity const transaction = loadTransaction(event) - const burn = new Burn(transaction.id + '#' + pool.txCount.toString()) + const burn = new Burn(transaction.id + '-' + event.logIndex.toString()) burn.transaction = transaction.id burn.timestamp = transaction.timestamp burn.pool = pool.id diff --git a/src/mappings/pool/collect.ts b/src/mappings/pool/collect.ts new file mode 100644 index 00000000..cc4e8080 --- /dev/null +++ b/src/mappings/pool/collect.ts @@ -0,0 +1,101 @@ +import { BigInt } from '@graphprotocol/graph-ts' + +import { Bundle, Collect, Factory, Pool, Token } from '../../types/schema' +import { Collect as CollectEvent } from '../../types/templates/Pool/Pool' +import { convertTokenToDecimal, loadTransaction } from '../../utils' +import { FACTORY_ADDRESS, ONE_BI } from '../../utils/constants' +import { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from '../../utils/intervalUpdates' +import { getTrackedAmountUSD } from '../../utils/pricing' + +export function handleCollect(event: CollectEvent): void { + const bundle = Bundle.load('1')! + const pool = Pool.load(event.address.toHexString()) + if (pool == null) { + return + } + const transaction = loadTransaction(event) + const factory = Factory.load(FACTORY_ADDRESS)! + + const token0 = Token.load(pool.token0) + const token1 = Token.load(pool.token1) + if (token0 == null || token1 == null) { + return + } + + // Get formatted amounts collected. + const collectedAmountToken0 = convertTokenToDecimal(event.params.amount0, token0.decimals) + const collectedAmountToken1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + const trackedCollectedAmountUSD = getTrackedAmountUSD( + collectedAmountToken0, + token0 as Token, + collectedAmountToken1, + token1 as Token + ) + + // Reset tvl aggregates until new amounts calculated + factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH) + + // Update globals + factory.txCount = factory.txCount.plus(ONE_BI) + + // update token data + token0.txCount = token0.txCount.plus(ONE_BI) + token0.totalValueLocked = token0.totalValueLocked.minus(collectedAmountToken0) + token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD)) + + token1.txCount = token1.txCount.plus(ONE_BI) + token1.totalValueLocked = token1.totalValueLocked.minus(collectedAmountToken1) + token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD)) + + // Adjust pool TVL based on amount collected. + pool.txCount = pool.txCount.plus(ONE_BI) + pool.totalValueLockedToken0 = pool.totalValueLockedToken0.minus(collectedAmountToken0) + pool.totalValueLockedToken1 = pool.totalValueLockedToken1.minus(collectedAmountToken1) + pool.totalValueLockedETH = pool.totalValueLockedToken0 + .times(token0.derivedETH) + .plus(pool.totalValueLockedToken1.times(token1.derivedETH)) + pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD) + + // Update aggregate fee collection values. + pool.collectedFeesToken0 = pool.collectedFeesToken0.plus(collectedAmountToken0) + pool.collectedFeesToken1 = pool.collectedFeesToken1.plus(collectedAmountToken1) + pool.collectedFeesUSD = pool.collectedFeesUSD.plus(trackedCollectedAmountUSD) + + // reset aggregates with new amounts + factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH) + factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) + + const collect = new Collect(transaction.id + '-' + event.logIndex.toString()) + collect.transaction = transaction.id + collect.timestamp = event.block.timestamp + collect.pool = pool.id + collect.owner = event.params.owner + collect.amount0 = collectedAmountToken0 + collect.amount1 = collectedAmountToken1 + collect.amountUSD = trackedCollectedAmountUSD + collect.tickLower = BigInt.fromI32(event.params.tickLower) + collect.tickUpper = BigInt.fromI32(event.params.tickUpper) + collect.logIndex = event.logIndex + + updateUniswapDayData(event) + updatePoolDayData(event) + updatePoolHourData(event) + updateTokenDayData(token0 as Token, event) + updateTokenDayData(token1 as Token, event) + updateTokenHourData(token0 as Token, event) + updateTokenHourData(token1 as Token, event) + + token0.save() + token1.save() + factory.save() + pool.save() + collect.save() + + return +} diff --git a/src/mappings/pool/index.ts b/src/mappings/pool/index.ts index a93f469c..6b3a0063 100644 --- a/src/mappings/pool/index.ts +++ b/src/mappings/pool/index.ts @@ -1,6 +1,7 @@ import { handleBurn } from './burn' +import { handleCollect } from './collect' import { handleInitialize } from './initialize' import { handleMint } from './mint' import { handleSwap } from './swap' -export { handleBurn, handleInitialize, handleMint, handleSwap } +export { handleBurn, handleCollect, handleInitialize, handleMint, handleSwap } diff --git a/src/mappings/pool/mint.ts b/src/mappings/pool/mint.ts index 892ed182..8fc50749 100644 --- a/src/mappings/pool/mint.ts +++ b/src/mappings/pool/mint.ts @@ -71,7 +71,7 @@ export function handleMint(event: MintEvent): void { factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD) const transaction = loadTransaction(event) - const mint = new Mint(transaction.id.toString() + '#' + pool.txCount.toString()) + const mint = new Mint(transaction.id.toString() + '-' + event.logIndex.toString()) mint.transaction = transaction.id mint.timestamp = transaction.timestamp mint.pool = pool.id diff --git a/src/mappings/pool/swap.ts b/src/mappings/pool/swap.ts index 320decfc..1743b261 100644 --- a/src/mappings/pool/swap.ts +++ b/src/mappings/pool/swap.ts @@ -127,7 +127,7 @@ export function handleSwap(event: SwapEvent): void { // create Swap event const transaction = loadTransaction(event) - const swap = new Swap(transaction.id + '#' + pool.txCount.toString()) + const swap = new Swap(transaction.id + '-' + event.logIndex.toString()) swap.transaction = transaction.id swap.timestamp = transaction.timestamp swap.pool = pool.id diff --git a/subgraph.yaml b/subgraph.yaml index 8f449b3b..10e7cb55 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -66,3 +66,5 @@ templates: handler: handleMint - event: Burn(indexed address,indexed int24,indexed int24,uint128,uint256,uint256) handler: handleBurn + - event: Collect(indexed address,address,indexed int24,indexed int24,uint128,uint128) + handler: handleCollect