From 91751da16ded0d2b6247f1226457b317b89b8c56 Mon Sep 17 00:00:00 2001 From: Ian Lapham Date: Mon, 22 Jun 2020 12:43:37 -0700 Subject: [PATCH 1/4] Update README.md --- README.md | 53 ++--------------------------------------------------- 1 file changed, 2 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index 7a165c72..dfa6d81d 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,4 @@ -# Uniswap V2 Subgraph +# Uniswap V2 Subgraph Testing -[Uniswap](https://uniswap.org/) is a decentralized protocol for automated token exchange on Ethereum. +This subgraph is for testing specifc interactions on a limited set of exchanges. -This subgraph dynamically tracks any pair created by the uniswap factory. It tracks of the current state of Uniswap contracts, and contains derived stats for things like historical data and USD prices. - -- aggregated data across pairs and tokens, -- data on individual pairs and tokens, -- data on transactions -- data on liquidity providers -- historical data on Uniswap, pairs or tokens, aggregated by day - -## Running Locally - -Make sure to update package.json settings to point to your own graph account. - -## Queries - -Below are a few ways to show how to query the uniswap-subgraph for data. The queries show most of the information that is queryable, but there are many other filtering options that can be used, just check out the [querying api](https://thegraph.com/docs/graphql-api). These queries can be used locally or in The Graph Explorer playground. - -## Key Entity Overviews - -#### UniswapFactory - -Contains data across all of Uniswap V2. This entity tracks important things like total liquidity (in ETH and USD, see below), all time volume, transaction count, number of pairs and more. - -#### Token -Contains data on a specific token. This token specific data is aggregated across all pairs, and is updated whenever there is a transaction involving that token. - -#### Pair -Contains data on a specific pair. - -#### Transaction -Every transaction on Uniswap is stored. Each transaction contains an array of mints, burns, and swaps that occured within it. - -#### Mint, Burn, Swap -These contain specifc information about a transaction. Things like which pair triggered the transaction, amounts, sender, recipient, and more. Each is linked to a parent Transaction entity. - -## Example Queries - -### Querying Aggregated Uniswap Data - -This query fetches aggredated data from all uniswap pairs and tokens, to give a view into how much activity is happening within the whole protocol. - -```graphql -{ - uniswapFactory(id: "1") { - pairCount - totalVolumeUSD - totalLiquidityUSD - } -} -``` From 1f9a0eac992c10a8ea2e4053b6b8535e80395372 Mon Sep 17 00:00:00 2001 From: Ian Lapham Date: Mon, 22 Jun 2020 12:43:51 -0700 Subject: [PATCH 2/4] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dfa6d81d..ad420c52 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ # Uniswap V2 Subgraph Testing -This subgraph is for testing specifc interactions on a limited set of exchanges. +This subgraph is for testing specifc interactions on a limited set of pairs. From fccf01e7ac154c83c8e21e3c39fb787fb6a559ba Mon Sep 17 00:00:00 2001 From: ianlapham Date: Mon, 22 Jun 2020 13:27:02 -0700 Subject: [PATCH 3/4] setup testing --- package.json | 2 +- schema.graphql | 28 +++++++- src/mappings/core.ts | 92 ++++++++++++++++++++----- src/mappings/dayUpdates.ts | 137 ++++++++++--------------------------- src/mappings/factory.ts | 11 ++- src/mappings/helpers.ts | 1 + src/mappings/pricing.ts | 80 +++++++++------------- subgraph.yaml | 2 +- 8 files changed, 184 insertions(+), 169 deletions(-) diff --git a/package.json b/package.json index 5abc8bba..99e93700 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "build": "graph build", "create-local": "graph create davekaj/uniswap --node http://127.0.0.1:8020", "deploy-local": "graph deploy davekaj/uniswap --debug --ipfs http://localhost:5001 --node http://127.0.0.1:8020", - "deploy": "graph deploy uniswap/uniswap-v2 --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/ --debug", + "deploy": "graph deploy ianlapham/uniswapbackup --ipfs https://api.thegraph.com/ipfs/ --node https://api.thegraph.com/deploy/ --debug", "deploy-staging": "graph deploy $THE_GRAPH_GITHUB_USER/$THE_GRAPH_SUBGRAPH_NAME /Uniswap --ipfs https://api.staging.thegraph.com/ipfs/ --node https://api.staging.thegraph.com/deploy/", "watch-local": "graph deploy graphprotocol/Uniswap2 --watch --debug --node http://127.0.0.1:8020/ --ipfs http://localhost:5001" }, diff --git a/schema.graphql b/schema.graphql index 1f59c490..3509dedc 100644 --- a/schema.graphql +++ b/schema.graphql @@ -1,6 +1,6 @@ -type UniswapFactory @entity { +type UniswapFactory @entity { # factory address - id: ID! + id: ID! # pair info pairCount: Int! @@ -96,6 +96,7 @@ type Pair @entity { type User @entity { id: ID! liquidityPositions: [LiquidityPosition!] @derivedFrom(field: "user") + usdSwapped: BigDecimal! } type LiquidityPosition @entity { @@ -160,6 +161,9 @@ type Burn @entity { # derived amount based on available prices of tokens amountUSD: BigDecimal + # mark uncomplete in ETH case + needsComplete: Boolean + # optional fee fields, if a Transfer event is fired in _mintFee feeTo: Bytes feeLiquidity: BigDecimal @@ -213,6 +217,26 @@ type UniswapDayData @entity { txCount: BigInt! } + +type PairHourData @entity { + id: ID! + hourIndex: Int! + pair: Pair! + + # reserves + reserve0: BigDecimal! + reserve1: BigDecimal! + + # derived liquidity + reserveUSD: BigDecimal! + + # volume stats + hourlyVolumeToken0: BigDecimal! + hourlyVolumeToken1: BigDecimal! + hourlyVolumeUSD: BigDecimal! + hourlyTxns: BigInt! +} + # Data accumulated and condensed into day stats for each exchange type PairDayData @entity { id: ID! diff --git a/src/mappings/core.ts b/src/mappings/core.ts index cb040885..0cdba6e2 100644 --- a/src/mappings/core.ts +++ b/src/mappings/core.ts @@ -14,7 +14,7 @@ import { Bundle } from '../types/schema' import { Pair as PairContract, Mint, Burn, Swap, Transfer, Sync } from '../types/templates/Pair/Pair' -import { updatePairDayData, updateTokenDayData, updateUniswapDayData } from './dayUpdates' +import { updatePairDayData, updateTokenDayData, updateUniswapDayData, updatePairHourData } from './dayUpdates' import { getEthPriceInUSD, findEthPerToken, getTrackedVolumeUSD, getTrackedLiquidityUSD } from './pricing' import { convertTokenToDecimal, @@ -32,6 +32,11 @@ function isCompleteMint(mintId: string): boolean { } export function handleTransfer(event: Transfer): void { + // ignore initial transfers for first adds + if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.value.equals(BigInt.fromI32(1000))) { + return + } + let factory = UniswapFactory.load(FACTORY_ADDRESS) let transactionHash = event.transaction.hash.toHexString() @@ -91,12 +96,8 @@ export function handleTransfer(event: Transfer): void { } } - // burn - if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.from.toHexString() == pair.id) { - pair.totalSupply = pair.totalSupply.minus(value) - pair.save() - - // this is a new instance of a logical burn + // case where direct send first on ETH withdrawls + if (event.params.to.toHexString() == pair.id) { let burns = transaction.burns let burn = new BurnEvent( event.transaction.hash @@ -107,6 +108,49 @@ export function handleTransfer(event: Transfer): void { burn.pair = pair.id burn.liquidity = value burn.timestamp = transaction.timestamp + burn.to = event.params.to + burn.sender = event.params.from + burn.needsComplete = true + burn.save() + burns.push(burn.id) + transaction.burns = burns + transaction.save() + } + + // burn + if (event.params.to.toHexString() == ADDRESS_ZERO && event.params.from.toHexString() == pair.id) { + pair.totalSupply = pair.totalSupply.minus(value) + pair.save() + + // this is a new instance of a logical burn + let burns = transaction.burns + let burn: BurnEvent + if (burns.length > 0) { + let currentBurn = BurnEvent.load(burns[burns.length - 1]) + if (currentBurn.needsComplete) { + burn = currentBurn as BurnEvent + } else { + burn = new BurnEvent( + event.transaction.hash + .toHexString() + .concat('-') + .concat(BigInt.fromI32(burns.length).toString()) + ) + burn.pair = pair.id + burn.liquidity = value + burn.timestamp = transaction.timestamp + } + } else { + burn = new BurnEvent( + event.transaction.hash + .toHexString() + .concat('-') + .concat(BigInt.fromI32(burns.length).toString()) + ) + burn.pair = pair.id + burn.liquidity = value + burn.timestamp = transaction.timestamp + } // if this logical burn included a fee mint, account for this if (mints.length !== 0 && !isCompleteMint(mints[mints.length - 1])) { @@ -120,10 +164,18 @@ export function handleTransfer(event: Transfer): void { transaction.mints = mints transaction.save() } + burn.save() - burns.push(burn.id) - transaction.burns = burns + // if accessing last one, replace it + if (burn.needsComplete) { + burns[burns.length - 1] = burn.id + } + // else add new one + else { + burns.push(burn.id) + } + transaction.burns = burns transaction.save() } @@ -181,12 +233,14 @@ export function handleSync(event: Sync): void { token1.save() // get tracked liquidity - will be 0 if neither is in whitelist - let trackedLiquidityETH: BigDecimal = getTrackedLiquidityUSD( - pair.reserve0, - token0 as Token, - pair.reserve1, - token1 as Token - ).div(bundle.ethPrice) + let trackedLiquidityETH: BigDecimal + if (bundle.ethPrice.notEqual(ZERO_BD)) { + trackedLiquidityETH = getTrackedLiquidityUSD(pair.reserve0, token0 as Token, pair.reserve1, token1 as Token).div( + bundle.ethPrice + ) + } else { + trackedLiquidityETH = ZERO_BD + } // use derived amounts within pair pair.trackedReserveETH = trackedLiquidityETH @@ -253,6 +307,7 @@ export function handleMint(event: Mint): void { // update day entities updatePairDayData(event) + updatePairHourData(event) updateUniswapDayData(event) updateTokenDayData(token0 as Token, event) updateTokenDayData(token1 as Token, event) @@ -298,16 +353,17 @@ export function handleBurn(event: Burn): void { uniswap.save() // update burn - burn.sender = event.params.sender + // burn.sender = event.params.sender burn.amount0 = token0Amount as BigDecimal burn.amount1 = token1Amount as BigDecimal - burn.to = event.params.to + // burn.to = event.params.to burn.logIndex = event.logIndex burn.amountUSD = amountTotalUSD as BigDecimal burn.save() // update day entities updatePairDayData(event) + updatePairHourData(event) updateUniswapDayData(event) updateTokenDayData(token0 as Token, event) updateTokenDayData(token1 as Token, event) @@ -338,6 +394,7 @@ export function handleSwap(event: Swap): void { // only accounts for volume through white listed tokens let trackedAmountUSD = getTrackedVolumeUSD(amount0Total, token0 as Token, amount1Total, token1 as Token) + let trackedAmountETH: BigDecimal if (bundle.ethPrice.equals(ZERO_BD)) { trackedAmountETH = ZERO_BD @@ -417,6 +474,7 @@ export function handleSwap(event: Swap): void { // update day entities updatePairDayData(event) + updatePairHourData(event) updateUniswapDayData(event) updateTokenDayData(token0 as Token, event) updateTokenDayData(token1 as Token, event) diff --git a/src/mappings/dayUpdates.ts b/src/mappings/dayUpdates.ts index f4734636..5464ddc2 100644 --- a/src/mappings/dayUpdates.ts +++ b/src/mappings/dayUpdates.ts @@ -1,3 +1,4 @@ +import { PairHourData } from './../types/schema' /* eslint-disable prefer-const */ import { BigInt, BigDecimal, EthereumEvent } from '@graphprotocol/graph-ts' import { Pair, Bundle, Token, UniswapFactory, UniswapDayData, PairDayData, TokenDayData } from '../types/schema' @@ -7,99 +8,6 @@ import { ONE_BI, ZERO_BD, ZERO_BI, FACTORY_ADDRESS } from './helpers' const maxTokenDayDatas = 10 const maxPairDayDatas = 10 -function updateStoredPairs(tokenDayData: TokenDayData, exchangeDayID: string): void { - let pairDayData = PairDayData.load(exchangeDayID.toString()) - let newList = tokenDayData.mostLiquidPairs - let alreadyInList = false - // check if exchange is already in list, make sure to compare on exchange - for (let i = 0; i < newList.length; i++) { - let currentPairData = PairDayData.load(newList[i]) - if (currentPairData.pairAddress.toHexString() == pairDayData.pairAddress.toHexString()) { - alreadyInList = true - newList[i] = pairDayData.id // reset to new day data - } - } - // base case max number - let minTokenLiquidity = new BigDecimal(BigInt.fromI32(I32.MAX_VALUE)) - let minIndex = 0 - if (newList.length < tokenDayData.maxStored && !alreadyInList) { - newList.push(pairDayData.id) - } else if (!alreadyInList) { - // loop through stored list and find min token liquidity - for (let i = 0; i < newList.length; i++) { - let currentPairs = tokenDayData.mostLiquidPairs as Array - let id = currentPairs[i] - let currentPairDayData = PairDayData.load(id.toString()) - let globalToken = tokenDayData.token - let localToken0 = currentPairDayData.token0 - // if our token of interest is token0, compare against that - if (globalToken == localToken0) { - if (currentPairDayData.reserve0 < minTokenLiquidity) { - minTokenLiquidity = currentPairDayData.reserve0 - minIndex = i - } - } - // our token of interest must be token 1 - else { - if (currentPairDayData.reserve1 < minTokenLiquidity) { - minTokenLiquidity = currentPairDayData.reserve1 - minIndex = i - } - } - } - // if current token has more liquidity than min, replace it - if (tokenDayData.totalLiquidityToken > minTokenLiquidity) { - newList[minIndex] = pairDayData.id - } - } - tokenDayData.mostLiquidPairs = newList - let token = Token.load(tokenDayData.token) - token.mostLiquidPairs = newList - token.save() - tokenDayData.save() -} - -/** - * Loop through stored token datas and find minimum liquidity in ETH. - * If new token is higher than min, replace min list at min index. - */ -function updateStoredTokens(tokenDayData: TokenDayData, dayID: i32): void { - let uniswap = UniswapFactory.load(FACTORY_ADDRESS) - let uniswapDayData = UniswapDayData.load(dayID.toString()) - let newList = uniswapDayData.mostLiquidTokens - let alreadyInList = false - // check if token is already in the list - for (let i = 0; i < newList.length; i++) { - let currentDayData = TokenDayData.load(newList[i].toString()) - if (currentDayData.token.toString() == tokenDayData.token.toString()) { - alreadyInList = true - newList[i] = tokenDayData.id - } - } - let minIndex = 0 - if (newList.length < uniswapDayData.maxStored && !alreadyInList) { - newList.push(tokenDayData.id) - } else if (!alreadyInList) { - let localMinLiquidity = new BigDecimal(BigInt.fromI32(I32.MAX_VALUE)) - // loop through stored list and find min liquidity - for (let i = 0; i < newList.length; i++) { - let currentDayData = TokenDayData.load(newList[i].toString()) - if (currentDayData.totalLiquidityETH < localMinLiquidity) { - localMinLiquidity = currentDayData.totalLiquidityETH - minIndex = i - } - } - // if current token has more liquidity than min, replace it - if (tokenDayData.totalLiquidityETH > localMinLiquidity) { - newList[minIndex] = tokenDayData.id - } - } - uniswapDayData.mostLiquidTokens = newList - uniswap.mostLiquidTokens = newList - uniswap.save() - uniswapDayData.save() -} - export function updateUniswapDayData(event: EthereumEvent): void { let uniswap = UniswapFactory.load(FACTORY_ADDRESS) let timestamp = event.block.timestamp.toI32() @@ -161,6 +69,37 @@ export function updatePairDayData(event: EthereumEvent): void { pairDayData.save() } +export function updatePairHourData(event: EthereumEvent): void { + let timestamp = event.block.timestamp.toI32() + let hourIndex = timestamp / 3600 // get unique hour within unix history + let hourStartIndex = hourIndex * 3600 // want the rounded effect + let hourPairID = event.address + .toHexString() + .concat('-') + .concat(BigInt.fromI32(hourIndex).toString()) + let pair = Pair.load(event.address.toHexString()) + let pairHourData = PairHourData.load(hourPairID) + if (pairHourData == null) { + let pairHourData = new PairHourData(hourPairID) + pairHourData.date = hourStartIndex + pairHourData.pair = event.address.toHexString() + pairHourData.reserve0 = ZERO_BD + pairHourData.reserve1 = ZERO_BD + pairHourData.reserveUSD = ZERO_BD + pairHourData.hourlyVolumeToken0 = ZERO_BD + pairHourData.hourlyVolumeToken1 = ZERO_BD + pairHourData.hourlyVolumeUSD = ZERO_BD + pairHourData.hourlyTxns = ZERO_BI + pairHourData.save() + } + pairHourData = PairHourData.load(hourPairID) + pairHourData.reserve0 = pair.reserve0 + pairHourData.reserve1 = pair.reserve1 + pairHourData.reserveUSD = pair.reserveUSD + pairHourData.hourlyTxns = pairHourData.hourlyTxns.plus(ONE_BI) + pairHourData.save() +} + export function updateTokenDayData(token: Token, event: EthereumEvent): void { let bundle = Bundle.load('1') let timestamp = event.block.timestamp.toI32() @@ -170,10 +109,6 @@ export function updateTokenDayData(token: Token, event: EthereumEvent): void { .toString() .concat('-') .concat(BigInt.fromI32(dayID).toString()) - let dayPairID = event.address - .toHexString() - .concat('-') - .concat(BigInt.fromI32(dayID).toString()) let tokenDayData = TokenDayData.load(tokenDayID) if (tokenDayData == null) { @@ -199,6 +134,10 @@ export function updateTokenDayData(token: Token, event: EthereumEvent): void { tokenDayData.totalLiquidityUSD = tokenDayData.totalLiquidityETH.times(bundle.ethPrice) tokenDayData.dailyTxns = tokenDayData.dailyTxns.plus(ONE_BI) tokenDayData.save() - updateStoredTokens(tokenDayData as TokenDayData, dayID) - updateStoredPairs(tokenDayData as TokenDayData, dayPairID) + + /** + * @todo test if this speeds up sync + */ + // updateStoredTokens(tokenDayData as TokenDayData, dayID) + // updateStoredPairs(tokenDayData as TokenDayData, dayPairID) } diff --git a/src/mappings/factory.ts b/src/mappings/factory.ts index 1ae2e605..ad03d65f 100644 --- a/src/mappings/factory.ts +++ b/src/mappings/factory.ts @@ -13,7 +13,17 @@ import { fetchTokenTotalSupply } from './helpers' +// ian coin 0x19c506211A26A67Ad7E6D45CD274bAD1863f8667 +// ian weth pair 0x07762371f09ba11c9df64ced901cad7ff5104100 + +let INCLUDED_PAIRS: string[] = ['0x07762371f09ba11c9df64ced901cad7ff5104100'] + export function handleNewPair(event: PairCreated): void { + log.debug('event address {}', [event.params.pair.toHexString()]) + if (!INCLUDED_PAIRS.includes(event.params.pair.toHexString())) { + return // ignore everything not on included list for testing + } + // load factory (create if first exchange) let factory = UniswapFactory.load(FACTORY_ADDRESS) if (factory == null) { @@ -125,4 +135,3 @@ export function handleNewPair(event: PairCreated): void { pair.save() factory.save() } -// } diff --git a/src/mappings/helpers.ts b/src/mappings/helpers.ts index 7e5ad956..3c3b7b23 100644 --- a/src/mappings/helpers.ts +++ b/src/mappings/helpers.ts @@ -149,6 +149,7 @@ export function createUser(address: Address): void { let user = User.load(address.toHexString()) if (user === null) { user = new User(address.toHexString()) + user.usdSwapped = ZERO_BD user.save() } } diff --git a/src/mappings/pricing.ts b/src/mappings/pricing.ts index 357291ec..ed72df10 100644 --- a/src/mappings/pricing.ts +++ b/src/mappings/pricing.ts @@ -3,44 +3,11 @@ import { Pair, Token, Bundle } from '../types/schema' import { BigDecimal, Address } from '@graphprotocol/graph-ts/index' import { ZERO_BD, factoryContract, ADDRESS_ZERO } from './helpers' -const USDC_WETH_PAIR = '0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc' // created 10008355 -const DAI_WETH_PAIR = '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11' // created block 10042267 -const USDT_WETH_PAIR = '0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852' // created block 10093341 const WETH_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' -// only count derived ETH prices in WETH pairs with at least this much WETH reserve -let ETH_RESERVE_THRESHOLD = BigDecimal.fromString('0.5') - -// return a weighted average price +// dummy for testing export function getEthPriceInUSD(): BigDecimal { - // fetch eth prices for each stablecoin - - let daiPair = Pair.load(DAI_WETH_PAIR) // dai is token0 - let usdcPair = Pair.load(USDC_WETH_PAIR) // usdc is token0 - let usdtPair = Pair.load(USDT_WETH_PAIR) // usdt is token1 - - // all 3 have been created - if (daiPair !== null && usdcPair !== null && usdtPair !== null) { - let totalLiquidityETH = daiPair.reserve1.plus(usdcPair.reserve1).plus(usdtPair.reserve0) - let daiWeight = daiPair.reserve1.div(totalLiquidityETH) - let usdcWeight = usdcPair.reserve1.div(totalLiquidityETH) - let usdtWeight = usdtPair.reserve0.div(totalLiquidityETH) - return daiPair.token0Price - .times(daiWeight) - .plus(usdcPair.token0Price.times(usdcWeight)) - .plus(usdtPair.token1Price.times(usdtWeight)) - // dai and USDC have been created - } else if (daiPair !== null && usdcPair !== null) { - let totalLiquidityETH = daiPair.reserve1.plus(usdcPair.reserve1) - let daiWeight = daiPair.reserve1.div(totalLiquidityETH) - let usdcWeight = usdcPair.reserve1.div(totalLiquidityETH) - return daiPair.token0Price.times(daiWeight).plus(usdcPair.token0Price.times(usdcWeight)) - // USDC is the only pair so far - } else if (usdcPair !== null) { - return usdcPair.token0Price - } else { - return ZERO_BD - } + return BigDecimal.fromString('200') } /** @@ -53,19 +20,11 @@ export function findEthPerToken(token: Token, maxDepthReached: boolean): BigDeci if (tokenWethPair.toHexString() != ADDRESS_ZERO) { let wethPair = Pair.load(tokenWethPair.toHexString()) if (wethPair.token0 == token.id) { - if (wethPair.reserve1.gt(ETH_RESERVE_THRESHOLD)) { - // our token is token 0 - return wethPair.token1Price - } else { - return ZERO_BD - } + // our token is token 0 + return wethPair.token1Price } else { - if (wethPair.reserve0.gt(ETH_RESERVE_THRESHOLD)) { - // our token is token 1 - return wethPair.token0Price - } else { - return ZERO_BD - } + // our token is token 1 + return wethPair.token0Price } } else if (!maxDepthReached) { let allPairs = token.allPairs as Array @@ -120,6 +79,8 @@ let WHITELIST: string[] = [ '0xc00e94cb662c3520282e6f5717214004a7f26888' // COMP ] +let MINIMUM_USD_THRESHOLD_NEW_PAIRS = BigDecimal.fromString('200000') + /** * Accepts tokens and amounts, return tracked amount based on token whitelist * If one token on whitelist, return amount in that token converted to USD. @@ -135,9 +96,32 @@ export function getTrackedVolumeUSD( let bundle = Bundle.load('1') let price0 = token0.derivedETH.times(bundle.ethPrice) let price1 = token1.derivedETH.times(bundle.ethPrice) + let pairAddress = factoryContract.getPair(Address.fromString(token0.id), Address.fromString(token1.id)) + let pair = Pair.load(pairAddress.toHexString()) + + // if only 1 LP, require high minimum reserve amount amount or return 0 + if (pair.liquidityPositions.length < 5) { + let reserve0USD = pair.reserve0.times(price0) + let reserve1USD = pair.reserve1.times(price1) + if (WHITELIST.includes(token0.id) && WHITELIST.includes(token1.id)) { + if (reserve0USD.plus(reserve1USD).lt(MINIMUM_USD_THRESHOLD_NEW_PAIRS)) { + return ZERO_BD + } + } + if (WHITELIST.includes(token0.id) && !WHITELIST.includes(token1.id)) { + if (reserve0USD.times(BigDecimal.fromString('2')).lt(MINIMUM_USD_THRESHOLD_NEW_PAIRS)) { + return ZERO_BD + } + } + if (!WHITELIST.includes(token0.id) && WHITELIST.includes(token1.id)) { + if (reserve1USD.times(BigDecimal.fromString('2')).lt(MINIMUM_USD_THRESHOLD_NEW_PAIRS)) { + return ZERO_BD + } + } + } - // both are whitelist tokens, take average of both amounts if (WHITELIST.includes(token0.id) && WHITELIST.includes(token1.id)) { + // both are whitelist tokens, take average of both amounts return tokenAmount0 .times(price0) .plus(tokenAmount1.times(price1)) diff --git a/subgraph.yaml b/subgraph.yaml index 75e3792c..c319c52b 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -10,7 +10,7 @@ dataSources: source: address: '0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f' abi: Factory - startBlock: 10000834 + startBlock: 10291800 mapping: kind: ethereum/events apiVersion: 0.0.3 From 3209e951b255dcd00d079f5b4c8e0ab5001717bf Mon Sep 17 00:00:00 2001 From: ianlapham Date: Mon, 22 Jun 2020 13:53:29 -0700 Subject: [PATCH 4/4] fix build --- schema.graphql | 2 +- src/mappings/dayUpdates.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/schema.graphql b/schema.graphql index 3509dedc..65cd4cb6 100644 --- a/schema.graphql +++ b/schema.graphql @@ -220,7 +220,7 @@ type UniswapDayData @entity { type PairHourData @entity { id: ID! - hourIndex: Int! + hourStartUnix: Int! pair: Pair! # reserves diff --git a/src/mappings/dayUpdates.ts b/src/mappings/dayUpdates.ts index 5464ddc2..ad0179e6 100644 --- a/src/mappings/dayUpdates.ts +++ b/src/mappings/dayUpdates.ts @@ -81,7 +81,7 @@ export function updatePairHourData(event: EthereumEvent): void { let pairHourData = PairHourData.load(hourPairID) if (pairHourData == null) { let pairHourData = new PairHourData(hourPairID) - pairHourData.date = hourStartIndex + pairHourData.hourStartUnix = hourStartIndex pairHourData.pair = event.address.toHexString() pairHourData.reserve0 = ZERO_BD pairHourData.reserve1 = ZERO_BD