From d7606668252b5592cae3565631507911fb011569 Mon Sep 17 00:00:00 2001 From: ianlapham Date: Tue, 4 May 2021 02:12:35 -0400 Subject: [PATCH] small updates for tracking swaps, pricing updates --- schema.graphql | 12 ++++++++++++ src/mappings/core.ts | 33 ++++++++++++++++++++++++-------- src/utils/constants.ts | 2 +- src/utils/index.ts | 14 +++++++------- src/utils/pricing.ts | 43 +++++++++++++++++++++++++++++++----------- subgraph.yaml | 4 ++-- 6 files changed, 79 insertions(+), 29 deletions(-) diff --git a/schema.graphql b/schema.graphql index 83e0b9d7..55cd0e5d 100644 --- a/schema.graphql +++ b/schema.graphql @@ -183,6 +183,10 @@ type Mint @entity { timestamp: BigInt! # pool position is within pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! # owner of position where liquidity minted to owner: Bytes! # the address that minted the liquidity @@ -212,6 +216,10 @@ type Burn @entity { transaction: Transaction! # pool position is within pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! # need this to pull recent txns for specific token or pool timestamp: BigInt! # owner of position where liquidity was burned @@ -243,6 +251,10 @@ type Swap @entity { timestamp: BigInt! # pool swap occured within pool: Pool! + # allow indexing by tokens + token0: Token! + # allow indexing by tokens + token1: Token! # sender of the swap sender: Bytes! # recipient of the swap diff --git a/src/mappings/core.ts b/src/mappings/core.ts index 758e0330..fcd82283 100644 --- a/src/mappings/core.ts +++ b/src/mappings/core.ts @@ -1,3 +1,4 @@ +import { log, Address } from '@graphprotocol/graph-ts' /* eslint-disable prefer-const */ import { Bundle, Pool, Token, Factory, Mint, Burn, Swap, Tick } from '../types/schema' import { BigDecimal, BigInt, store } from '@graphprotocol/graph-ts' @@ -12,8 +13,12 @@ export function handleInitialize(event: Initialize): void { let pool = Pool.load(event.address.toHexString()) pool.sqrtPrice = event.params.sqrtPriceX96 pool.tick = BigInt.fromI32(event.params.tick) + // update token prices + let token0 = Token.load(pool.token0) + let token1 = Token.load(pool.token1) + // token prices - let prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice) + let prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token) pool.token0Price = prices[0] pool.token1Price = prices[1] pool.save() @@ -26,8 +31,6 @@ export function handleInitialize(event: Initialize): void { updatePoolDayData(event) // update token prices - let token0 = Token.load(pool.token0) - let token1 = Token.load(pool.token1) token0.derivedETH = findEthPerToken(token0 as Token) token1.derivedETH = findEthPerToken(token1 as Token) token0.save() @@ -44,6 +47,10 @@ export function handleMint(event: MintEvent): void { let token1 = Token.load(pool.token1) let amount0 = convertTokenToDecimal(event.params.amount0, token0.decimals) let amount1 = convertTokenToDecimal(event.params.amount1, token1.decimals) + if (event.transaction.from === Address.fromString('0x74Aa01d162E6dC6A657caC857418C403D48E2D77')) { + log.debug('mybug token0 orice', [token0.derivedETH.toString()]) + log.debug('mybug token1 orice', [token1.derivedETH.toString()]) + } let amountUSD = amount0 .times(token0.derivedETH.times(bundle.ethPriceUSD)) @@ -84,6 +91,8 @@ export function handleMint(event: MintEvent): void { mint.transaction = transaction.id mint.timestamp = transaction.timestamp mint.pool = pool.id + mint.token0 = pool.token0 + mint.token1 = pool.token1 mint.owner = event.params.owner mint.sender = event.params.sender mint.origin = event.transaction.from @@ -101,10 +110,10 @@ export function handleMint(event: MintEvent): void { let lowerTickId = poolAddress + '#' + BigInt.fromI32(event.params.tickLower).toString() let upperTickId = poolAddress + '#' + BigInt.fromI32(event.params.tickUpper).toString() - + let lowerTick = Tick.load(lowerTickId) let upperTick = Tick.load(upperTickId) - + if (lowerTick === null) { lowerTick = createTick(lowerTickId, lowerTickIdx, pool.id, event) } @@ -187,6 +196,8 @@ export function handleBurn(event: BurnEvent): void { burn.transaction = transaction.id burn.timestamp = transaction.timestamp burn.pool = pool.id + burn.token0 = pool.token0 + burn.token1 = pool.token1 burn.owner = event.params.owner burn.origin = event.transaction.from burn.amount = event.params.amount @@ -216,13 +227,13 @@ export function handleBurn(event: BurnEvent): void { // If liquidity gross is zero then there are no positions starting at or ending at the tick. // It is now safe to remove the tick from the data store. if (lowerTick.liquidityGross.equals(ZERO_BD)) { - store.remove('Tick', lowerTickId); + store.remove('Tick', lowerTickId) } else { lowerTick.save() } if (upperTick.liquidityGross.equals(ZERO_BD)) { - store.remove('Tick', upperTickId); + store.remove('Tick', upperTickId) } else { upperTick.save() } @@ -266,6 +277,9 @@ export function handleSwap(event: SwapEvent): void { let amountTotalETH = amount0ETH.plus(amount1ETH).div(BigDecimal.fromString('2')) let amountTotalUSD = amount0USD.plus(amount1USD).div(BigDecimal.fromString('2')) + log.debug('mybug token0 Eth: {}', [token0.derivedETH.toString()]) + log.debug('mybug token1 Eth: {}', [token1.derivedETH.toString()]) + // global updates factory.txCount = factory.txCount.plus(ONE_BI) factory.totalVolumeETH = factory.totalVolumeETH.plus(amount0ETH).plus(amount1ETH) @@ -300,7 +314,7 @@ export function handleSwap(event: SwapEvent): void { token1.volumeUSD = token1.volumeUSD.plus(amountTotalUSD) // updated pool rates - let prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice) + let prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token) pool.token0Price = prices[0] pool.token1Price = prices[1] pool.save() @@ -333,6 +347,8 @@ export function handleSwap(event: SwapEvent): void { swap.transaction = transaction.id swap.timestamp = transaction.timestamp swap.pool = pool.id + swap.token0 = pool.token0 + swap.token1 = pool.token1 swap.sender = event.params.sender swap.origin = event.transaction.from swap.recipient = event.params.recipient @@ -365,6 +381,7 @@ export function handleSwap(event: SwapEvent): void { token1DayData.volumeUSD = token1DayData.volumeUSD.plus(amountTotalUSD) token1DayData.untrackedVolumeUSD = token1DayData.untrackedVolumeUSD.plus(amountTotalUSD) + swap.save() token0DayData.save() token1DayData.save() uniswapDayData.save() diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 10d59e10..a3c793ed 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -3,7 +3,7 @@ import { BigInt, BigDecimal, Address } from '@graphprotocol/graph-ts' import { Factory as FactoryContract } from '../types/templates/Pool/Factory' export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000' -export const FACTORY_ADDRESS = '0xFeabCc62240297F1e4b238937D68e7516f0918D7' +export const FACTORY_ADDRESS = '0x815BCC87613315327E04e4A3b7c96a79Ae80760c' export let ZERO_BI = BigInt.fromI32(0) export let ONE_BI = BigInt.fromI32(1) diff --git a/src/utils/index.ts b/src/utils/index.ts index fe9123a7..36f62b00 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -14,20 +14,20 @@ export function exponentToBigDecimal(decimals: BigInt): BigDecimal { export function bigDecimalExponated(value: BigDecimal, power: BigInt): BigDecimal { if (power.equals(ZERO_BI)) { - return ONE_BD; + return ONE_BD } - let negativePower = power.lt(ZERO_BI); - let result = ZERO_BD.plus(value); - let powerAbs = power.abs(); + let negativePower = power.lt(ZERO_BI) + let result = ZERO_BD.plus(value) + let powerAbs = power.abs() for (let i = ONE_BI; i.lt(powerAbs); i = i.plus(ONE_BI)) { result = result.times(value) } - + if (negativePower) { result = ONE_BD.div(result) } - - return result; + + return result } export function tokenAmountToDecimal(tokenAmount: BigInt, exchangeDecimals: BigInt): BigDecimal { diff --git a/src/utils/pricing.ts b/src/utils/pricing.ts index 247f1fdf..84fa4df0 100644 --- a/src/utils/pricing.ts +++ b/src/utils/pricing.ts @@ -2,18 +2,24 @@ import { ONE_BD, ZERO_BD } from './constants' import { Pool, Token } from './../types/schema' import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' +import { exponentToBigDecimal } from '../utils/index' let Q192 = 2 ** 192 -export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt): BigDecimal[] { +export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, token1: Token): BigDecimal[] { let num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal() let denom = BigDecimal.fromString(Q192.toString()) - let price1 = num.div(denom) + let price1 = num + .div(denom) + .times(exponentToBigDecimal(token0.decimals)) + .div(exponentToBigDecimal(token1.decimals)) + let price0 = BigDecimal.fromString('1').div(price1) + return [price0, price1] } const WETH_ADDRESS = '0xc778417e063141139fce010982780140aa0cd5ab' -const DAI_WETH_03_POOL = '0x8ffb36fe19aaa22bf11f6a4f3dbcd4ae13842a67' +const DAI_WETH_03_POOL = '0x62fc2179597e23321cc2a77b1a77b72c98f5e1a5' export function getEthPriceInUSD(): BigDecimal { // fetch eth prices for each stablecoin @@ -25,15 +31,14 @@ export function getEthPriceInUSD(): BigDecimal { } } -// token where amounts should contribute to tracked volume and liquidity -// let FEE_LEVELS_BIPS: number[] = [500, 3000, 10000] - // token where amounts should contribute to tracked volume and liquidity export let WHITELIST_TOKENS: string[] = [ WETH_ADDRESS, // WETH '0xc7ad46e0b8a400bb3c915120d284aafba8fc4735' // DAI ] +let MINIMUM_ETH_LOCKED = BigDecimal.fromString('1.5') + /** * Search through graph to find derived Eth per token. * @todo update to be derived ETH (add stablecoin estimates) @@ -43,19 +48,35 @@ export function findEthPerToken(token: Token): BigDecimal { return ONE_BD } let whiteList = token.whitelistPools + // for now just take USD from pool with greatest TVL + // need to update this to actually detect best rate based on liquidity distribution + let largestLiquidityETH = ZERO_BD + let priceSoFar = ZERO_BD + for (let i = 0; i < whiteList.length; ++i) { let poolAddress = whiteList[i] let pool = Pool.load(poolAddress) if (pool.token0 == token.id) { + // whitelist token is token1 let token1 = Token.load(pool.token1) - // token1 per our token * Eth per token1 - return pool.token1Price.times(token1.derivedETH as BigDecimal) + // get the derived ETH in pool + let ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH) + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) { + largestLiquidityETH = ethLocked + // token1 per our token * Eth per token1 + priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal) + } } if (pool.token1 == token.id) { let token0 = Token.load(pool.token0) - // token0 per our token * ETH per token0 - return pool.token0Price.times(token0.derivedETH as BigDecimal) + // get the derived ETH in pool + let ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH) + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(MINIMUM_ETH_LOCKED)) { + largestLiquidityETH = ethLocked + // token0 per our token * ETH per token0 + priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal) + } } } - return ZERO_BD // nothing was found return 0 + return priceSoFar // nothing was found return 0 } diff --git a/subgraph.yaml b/subgraph.yaml index 1e453a9a..bb131414 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -8,9 +8,9 @@ dataSources: name: Factory network: rinkeby source: - address: '0xFeabCc62240297F1e4b238937D68e7516f0918D7' + address: '0x815BCC87613315327E04e4A3b7c96a79Ae80760c' abi: Factory - startBlock: 8459128 + startBlock: 8494387 mapping: kind: ethereum/events apiVersion: 0.0.3