diff --git a/README.md b/README.md index e43a8fda..e2bfdb6e 100644 --- a/README.md +++ b/README.md @@ -12,3 +12,8 @@ Pending Changes at same URL 2. Install postgres: `brew install postgresql` 3. `yarn run build:docker` 4. `yarn run test` + +### Adding New Chains + +1. Create a new subgraph config in `src/utils/chains.ts`. This will require adding a new `ChainId`. Set the `SELECTED_CHAIN` in `getSubgraphConfig()` to be this new `ChainId`. +2. Add a new entry in `networks.json` for the new chain. The network name should be derived from the CLI Name in The Graph's [supported networks documenation](https://thegraph.com/docs/en/developing/supported-networks/). The factory address can be derived from Uniswap's [deployments documentation](https://docs.uniswap.org/contracts/v3/reference/deployments/ethereum-deployments). diff --git a/networks.json b/networks.json new file mode 100644 index 00000000..68d113ad --- /dev/null +++ b/networks.json @@ -0,0 +1,56 @@ +{ + "arbitrum-one": { + "Factory": { + "address": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "startBlock": 165 + } + }, + "avalanche": { + "Factory": { + "address": "0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD", + "startBlock": 27832971 + } + }, + "base": { + "Factory": { + "address": "0x33128a8fC17869897dcE68Ed026d694621f6FDfD", + "startBlock": 2009445 + } + }, + "blast-mainnet": { + "Factory": { + "address": "0x792edAdE80af5fC680d96a2eD80A44247D2Cf6Fd", + "startBlock": 400903 + } + }, + "bsc": { + "Factory": { + "address": "0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7", + "startBlock": 12369621 + } + }, + "celo": { + "Factory": { + "address": "0xAfE208a311B21f13EF87E33A90049fC17A7acDEc", + "startBlock": 13916355 + } + }, + "mainnet": { + "Factory": { + "address": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "startBlock": 12369621 + } + }, + "matic": { + "Factory": { + "address": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "startBlock": 22757547 + } + }, + "optimism": { + "Factory": { + "address": "0x1F98431c8aD98523631AE4a59f267346ea31F984", + "startBlock": 0 + } + } +} diff --git a/schema.graphql b/schema.graphql index 5af3066e..19fb45c8 100644 --- a/schema.graphql +++ b/schema.graphql @@ -64,7 +64,9 @@ type Token @entity { totalValueLockedUSD: BigDecimal! # TVL derived in USD untracked totalValueLockedUSDUntracked: BigDecimal! - # derived price in ETH + # NOTE: for chains where ETH is not the native token, this will be the derived + # price of that chain's native token, effectively, this should be renamed + # derivedNative derivedETH: BigDecimal! # pools token is in that are white listed for USD pricing whitelistPools: [Pool!]! diff --git a/src/backfill/index.ts b/src/backfill/index.ts new file mode 100644 index 00000000..82b96d78 --- /dev/null +++ b/src/backfill/index.ts @@ -0,0 +1,128 @@ +/* eslint-disable prefer-const */ +import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts' + +import { ERC20 } from '../types/Factory/ERC20' +import { Pool as PoolABI } from '../types/Factory/Pool' +import { Pool, Token } from '../types/schema' +import { Pool as PoolTemplate } from '../types/templates' +import { convertTokenToDecimal } from '../utils' +import { ZERO_BD, ZERO_BI } from '../utils/constants' +import { StaticTokenDefinition } from '../utils/staticTokenDefinition' +import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from '../utils/token' + +function populateToken(tokenAddress: string, tokenOverrides: StaticTokenDefinition[]): void { + let token = Token.load(tokenAddress) + if (token != null) { + return + } + token = new Token(tokenAddress) + token.symbol = fetchTokenSymbol(Address.fromString(tokenAddress), tokenOverrides) + token.name = fetchTokenName(Address.fromString(tokenAddress), tokenOverrides) + token.totalSupply = fetchTokenTotalSupply(Address.fromString(tokenAddress)) + let decimals = fetchTokenDecimals(Address.fromString(tokenAddress), tokenOverrides) + if (decimals === null) { + return + } + token.decimals = decimals + token.derivedETH = ZERO_BD + token.volume = ZERO_BD + token.volumeUSD = ZERO_BD + token.feesUSD = ZERO_BD + token.untrackedVolumeUSD = ZERO_BD + token.totalValueLocked = ZERO_BD + token.totalValueLockedUSD = ZERO_BD + token.totalValueLockedUSDUntracked = ZERO_BD + token.txCount = ZERO_BI + token.poolCount = ZERO_BI + token.whitelistPools = [] + token.save() +} + +/** + * Create entries in store for each pool and token + * before regenesis. + */ +export function populateEmptyPools( + event: ethereum.Event, + poolMappings: Array
, + whitelistTokens: string[], + tokenOverrides: StaticTokenDefinition[], +): void { + let length = poolMappings.length + for (let i = 0; i < length; ++i) { + let poolMapping = poolMappings[i] + let newAddress = poolMapping[1] + let token0Address = poolMapping[2] + let token1Address = poolMapping[3] + + let poolContract = PoolABI.bind(newAddress) + let pool = new Pool(newAddress.toHexString()) as Pool + pool.createdAtBlockNumber = event.block.number + pool.createdAtTimestamp = event.block.timestamp + pool.token0 = token0Address.toHexString() + pool.token1 = token1Address.toHexString() + pool.liquidity = poolContract.liquidity() + pool.sqrtPrice = ZERO_BI + pool.token0Price = ZERO_BD + pool.token1Price = ZERO_BD + pool.observationIndex = ZERO_BI + pool.liquidityProviderCount = ZERO_BI + pool.txCount = ZERO_BI + pool.totalValueLockedToken0 = ZERO_BD + pool.totalValueLockedToken1 = ZERO_BD + pool.totalValueLockedETH = ZERO_BD + pool.totalValueLockedUSD = ZERO_BD + pool.totalValueLockedUSDUntracked = ZERO_BD + pool.volumeToken0 = ZERO_BD + pool.volumeToken1 = ZERO_BD + pool.volumeUSD = ZERO_BD + pool.untrackedVolumeUSD = ZERO_BD + pool.feesUSD = ZERO_BD + pool.collectedFeesToken0 = ZERO_BD + pool.collectedFeesToken1 = ZERO_BD + pool.collectedFeesUSD = ZERO_BD + + // need fee tier + let feeTier = poolContract.fee() + pool.feeTier = BigInt.fromI32(feeTier) + + // create token entities if needed + populateToken(token0Address.toHexString(), tokenOverrides) + populateToken(token1Address.toHexString(), tokenOverrides) + let token0 = Token.load(token0Address.toHexString()) + let token1 = Token.load(token1Address.toHexString()) + + if (token0 && token1) { + if (whitelistTokens.includes(pool.token0)) { + let newPools = token1.whitelistPools + newPools.push(pool.id) + token1.whitelistPools = newPools + } + + if (whitelistTokens.includes(token1.id)) { + let newPools = token0.whitelistPools + newPools.push(pool.id) + token0.whitelistPools = newPools + } + + // populate the TVL by call contract balanceOf + let token0Contract = ERC20.bind(Address.fromString(pool.token0)) + let tvlToken0Raw = token0Contract.balanceOf(Address.fromString(pool.id)) + let tvlToken0Adjusted = convertTokenToDecimal(tvlToken0Raw, token0.decimals) + pool.totalValueLockedToken0 = tvlToken0Adjusted + token0.totalValueLocked = tvlToken0Adjusted + + let token1Contract = ERC20.bind(Address.fromString(pool.token1)) + let tvlToken1Raw = token1Contract.balanceOf(Address.fromString(pool.id)) + let tvlToken1Adjusted = convertTokenToDecimal(tvlToken1Raw, token1.decimals) + pool.totalValueLockedToken1 = tvlToken1Adjusted + token1.totalValueLocked = tvlToken1Adjusted + + // add pool to tracked address and store entities + PoolTemplate.create(Address.fromString(pool.id)) + token0.save() + token1.save() + pool.save() + } + } +} diff --git a/src/backfill/poolMappings.ts b/src/backfill/poolMappings.ts new file mode 100644 index 00000000..ba9c9e24 --- /dev/null +++ b/src/backfill/poolMappings.ts @@ -0,0 +1,633 @@ +/** + * Mapping provided by Optimism team. + * Includes old and updated Pool address for Optimism pools pre-regenesis. + * Need as subgraph indexer has no knowledge for pre-regenesis events. + * 0: old address + * 1: new address + * 2: token0 address + * 3: token1 address + */ + +import { Address } from '@graphprotocol/graph-ts' + +// eslint-disable-next-line prefer-const +export const OPTIMISM_POOL_MAPPINGS: Array = [ + [ + Address.fromString('0x8c505fd76eed0945699265c7c7e5bbf756b7e5ad'), + Address.fromString('0x03af20bdaaffb4cc0a521796a223f7d85e2aac31'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x8c505fd76eed0945699265c7c7e5bbf756b7e5ad'), + Address.fromString('0x827f0a2a4376bc26729f398b865f424dc8456841'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xdd54251a35078ba39e3ad5fb059f9aa243693b9d'), + Address.fromString('0x73b14a78a0d396c521f954532d43fd5ffe385216'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0x0ad1af4178e17d7f41dbcdf9d573701bef5eb501'), + Address.fromString('0xdd0c6bae8ad5998c358b823df15a2a4181da1b80'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xdf42e37f057c61765fe7204642c4d2e5ff929cfe'), + Address.fromString('0x815ae7bf44dda74ed9274377ed711efc8b567911'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x6b952bfbfda057a7f288edaa9f611cd446ddbe22'), + Address.fromString('0x95d9d28606ee55de7667f0f176ebfc3215cfd9c0'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x0bec645f0373750fe0256ee0e7b06d63eae5e04d'), + Address.fromString('0x2df05e4cdbd758cb1a99a34bb0d767e040d6b078'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x6afd8618459729da24ee36978567fb04fe5fd1bd'), + Address.fromString('0x85c31ffa3706d1cce9d525a00f1c7d4a2911754c'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0xa61dea82c7c3e64a6a80550aacb251eed604b46b'), + Address.fromString('0x37ffd11972128fd624337ebceb167c8c0a5115ff'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0xcf438c19332d507326210da527fb9cf792fd3e18'), + Address.fromString('0xc858a329bf053be78d6239c4a4343b8fbd21472b'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xaddd011cb3b61d0dc4f85c2661cc9bd1bd640067'), + Address.fromString('0xb29a022ff4b37bdfb21e5f1daff4af5a22aa9510'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0x47516ccba929c607e14dbd02f2ebac1e7960b1f8'), + Address.fromString('0x0392b358ce4547601befa962680bede836606ae2'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0x13b2d83ec506b5c770f64ee0f564ff9719c74071'), + Address.fromString('0xfea834a5c47b923add607cc5b96288d18ffb9c3f'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0xd20bf925e04933ff79274479009218dedab6657f'), + Address.fromString('0xac721d2e27ca148f505b5106fc95e594c78ace5b'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x7678f1e1ed90efec8757af161ab25bf1e8e00238'), + Address.fromString('0xa13514b5444e50067f6e48c386016b211773cf9e'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x2816913eda0010af856d323724f521fb702a25a7'), + Address.fromString('0xcf2aebb91fec906f51fc11cd57035a09d8b16965'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x2419a5fee0f8e0192869507ed6a301382ad9edda'), + Address.fromString('0xea0f33940eb221aaad9360891cab08ef4f1f0703'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x0ccf6bf2df83d250d0f6a636215ef7d19f86dd01'), + Address.fromString('0x703eb589321f3dc7408e9dde01b790e64a9fe4e9'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x1135e9ce18373238c77ff602a9b0a579ca86eb8e'), + Address.fromString('0xc22662b904d98e45f89e030201355c3e372cc819'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x2f5ccaf670e9c5f4336c127a29fdd4932f238069'), + Address.fromString('0x1aa9b4d9933ff96b2011fddd764240d4a16b7c07'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x0f641370eb5cb4f0b0d58140d5fb2f97ffcbfce5'), + Address.fromString('0x2459023a29d3b07711b8b916d86aa7e8a14747af'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xa14e5b3ba5dd981b536e0950390b03972b795018'), + Address.fromString('0xadb35413ec50e0afe41039eac8b930d313e94fa4'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xbdb9a8279a525bafe9be7efb9b5df79b18eeb23f'), + Address.fromString('0x84eb2c5c23999b3ddc87be10f15ccec5d22c7d97'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xa194977b416f082f71a0362041b57208c91ee1c1'), + Address.fromString('0x2e80d5a7b3c613d854ee43243ff09808108561eb'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xc3099d7fd3fc7d4feea11911fbe6eadc94c7c07a'), + Address.fromString('0x3d44cc727fe2f603e4929be164c70edb3b498b5f'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xfe901e734c8c55645731acd4eb0be963d2a85b94'), + Address.fromString('0xa588c9d2884c60b098c5ad028ec2f4a1fab772b5'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0xeaa5ba3ef450887e4d5a627700aef3c1a16d4090'), + Address.fromString('0xc53f2be3331926d2f30ee2b10362bb45fdbe7bf6'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0x263312f667279452ad44cda7971fe93f18b6dad4'), + Address.fromString('0x0843e0f56b9e7fdc4fb95fabba22a01ef4088f41'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x051580636f94b8b6ba69b879958939d324d8f650'), + Address.fromString('0x8184f5cf4921558c201923ef6d7d5258a6efa31f'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xbb8a699cbd6b45f7c31dcd14bd6d965ab4293e2c'), + Address.fromString('0x8b057f0ccd9fb78f688472574cf3f9d2322f5454'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x98fd8560e184136f482054c19a63e644240e30f4'), + Address.fromString('0x9f08065dfc4817a0a56db7bcab757e86399bc51d'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xbeafe824395fff8df37c4814e8de9d455e79cdad'), + Address.fromString('0x7628784d2c5d47fcd5479ba812343b1aabad6484'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xcfe7288e10994555ca97dfa2d0c50e55a4d4dc39'), + Address.fromString('0xceb488e01c8e2e669c40b330bfc1440921c9ebe2'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0x4cff717ff0b0a4a3578e8bbb7a5f06d32574238b'), + Address.fromString('0x25e412992634b93a025e2a538c53222a8c62e2d6'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0x072611197970d6a9e57680f97f177ff947f09139'), + Address.fromString('0xc0f184c6c4832b3ed861bd5b05722792ffa64abd'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0x380ff418bf1589b46e9660c6b2197b4ce8ae8a12'), + Address.fromString('0xf046d8b7365d8abe5a8f8301c669b4b5284fc21d'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xac8c823548f13874dcfc76029089de01f4adc1d3'), + Address.fromString('0x1f2390484dfe2d8900bc91c7111d274b7b2d63a1'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x8cf0a5fdcaed0956a3221e1dd5219bb14f092595'), + Address.fromString('0xa0959d2dcd9dd56bf080a10cfe29eeb401344e3d'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xaf00e47d2fe45befc4540fe02a87cb053e252065'), + Address.fromString('0x30be2fff09fcd820a1d472e646bd233dbd812133'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x00a0e3cd857a7e5676c901bd349ed1d6afb59fb3'), + Address.fromString('0x3202c46666e774b44ba463eafaa6da9a968a058f'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x4200000000000000000000000000000000000006'), + ], + [ + Address.fromString('0x90fc3f5f84fb868b7693b1f2690b91f28c1600d0'), + Address.fromString('0x85e8d0fddf559a57aac6404e7695142cd53eb808'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0xc87adb8ac31434e96b429ced522ed84a2ce707a6'), + Address.fromString('0x22fc5dc36811d15fafde7cc7900ae73a538e59e0'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x466fd9d58bdd0e246cbe9112d95d077b81b341af'), + Address.fromString('0xe7ee03b72a89f87d161425e42548bd5492d06679'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x7b6467b86878b86163bcb3162d84e34ea5c7389b'), + Address.fromString('0xfe1bd31a79163d6277ab8c2917d7857c225db065'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xc24383ba6d156706864a48f50fc01e89c0bf11d7'), + Address.fromString('0xbf595eb9a512b1c274125264aef84a2847158eb3'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0x93d9dfb5caf591df911b251db4d76cd95f4644b7'), + Address.fromString('0x124657e5bb6afc12a15c439d08fc80070f9a1a1e'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x36c95ae265883c2b19e61997760b110cc05e4a60'), + Address.fromString('0xd6101cda1a51924e249132cbcae82bfcd0a91fbc'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xd515990647c39c4a0b8c03f811f9b746958a0eec'), + Address.fromString('0x19ea026886cbb7a900ecb2458636d72b5cae223b'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x4200000000000000000000000000000000000006'), + ], + [ + Address.fromString('0x3b6479c7748eb5b143a3a52d237c0097734b811b'), + Address.fromString('0x5aacc66073cb0c3064353f1441c2e04170b4dbbf'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xc5Db22719A06418028A40A9B5E9A7c02959D0d08'), + ], + [ + Address.fromString('0x2d073707207098cc69e8e86c6a3fd12644b8a1b2'), + Address.fromString('0x4284b21e76d1b3977cab8f0032867e00e6eea382'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0xc5Db22719A06418028A40A9B5E9A7c02959D0d08'), + ], + [ + Address.fromString('0x015986c7074ec1eeae0387a8baf485fd9d811b7d'), + Address.fromString('0x2f10a1a3e640ad1615cbedf95a1749a4af88cbc0'), + Address.fromString('0xB548f63D4405466B36C0c0aC3318a22fDcec711a'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x4a88e6fa2afad460befd586fc1581f322308c490'), + Address.fromString('0x32846ede08688d10a9da59387707a8fbb0790fa7'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xab7bAdEF82E9Fe11f6f33f87BC9bC2AA27F2fCB5'), + ], + [ + Address.fromString('0xccf24898ca659afa8cb6a3bdb8a2e0a2debda12d'), + Address.fromString('0xbdb6371fffc1753b33b87c68c827eb7978670515'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + ], + [ + Address.fromString('0x856d50c587824f84de481ea706208b03db38f6f2'), + Address.fromString('0x2eee8ed7df992f23d7554b0db8835d483cce901c'), + Address.fromString('0x298B9B95708152ff6968aafd889c6586e9169f1D'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0xe3d8cfc3a0b43d2288b3da41563b1fe0623209de'), + Address.fromString('0x65dc095b35679005229896566928f6852948092b'), + Address.fromString('0x298B9B95708152ff6968aafd889c6586e9169f1D'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + ], + [ + Address.fromString('0x62196490fcf045437e5e4cb49228bbd778b7196d'), + Address.fromString('0x2d6497dd08a1620d386ce708edac50aaec332415'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0xe405de8f52ba7559f9df3c368500b6e6ae6cee49'), + ], + [ + Address.fromString('0x3b1f6287be238c9b0a4b48d85d2359d58aaa9683'), + Address.fromString('0x039ae8860fbfdf61f654b1a5b55cc3aa753f5842'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x91e50b184ea237b3da1c005ee5d2a17a904a34c6'), + Address.fromString('0x24342b5d46f69ba05c09becdd00e5324f9f0f7ca'), + Address.fromString('0x298B9B95708152ff6968aafd889c6586e9169f1D'), + Address.fromString('0x4200000000000000000000000000000000000006'), + ], + [ + Address.fromString('0x518767d8ef1acffd978581c16789f8a2803f9bef'), + Address.fromString('0xf0d0e52da1fdde512af299f3d8ea1c5e3bebb96f'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xe3C332a5DcE0e1d9bC2cC72A68437790570C28a4'), + ], + [ + Address.fromString('0xc2c0786e85ac9b0b223966d040ebc641fa44225e'), + Address.fromString('0xb589969d38ce76d3d7aa319de7133bc9755fd840'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0xa2389a4ee391b4b04ae8dc664664190f3d28f2fe'), + Address.fromString('0x8eda97883a1bc02cf68c6b9fb996e06ed8fdb3e5'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xf9ca53854d1ac7adb43d9447aa87f17fe1454e31'), + Address.fromString('0x100bdc1431a9b09c61c0efc5776814285f8fb248'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x4893c5f29301cfd7a6527331f3e06ea82e68a952'), + Address.fromString('0xe229ce1cdbea9983362ca29f0f0b2c70bb2dacdf'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xf2e805fe3b15297e1df03b6036d01b32ab8f7998'), + Address.fromString('0xd9b160620447d9a9a6ca90c0450f5490e5219257'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x6663eea65669978481bae55814cbc496acd50352'), + Address.fromString('0x1179b19438a622fe36be5f9c073b700420384397'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x7bbc5726e6c2640ed0f0fda1546dc232dc5db89c'), + Address.fromString('0xf3f3433c3a97f70349c138ada81da4d3554982db'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x0d4294ae819ff83a4e2a99db8d06cdd025c19218'), + Address.fromString('0x85149247691df622eaf1a8bd0cafd40bc45154a9'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0x9e845c705aba9a2ca6e97c2423797e18a98d34c0'), + Address.fromString('0x6fa1ea0ccbbe9b2ad52440c88a47b5d73cd9a731'), + Address.fromString('0x298B9B95708152ff6968aafd889c6586e9169f1D'), + Address.fromString('0x4200000000000000000000000000000000000006'), + ], + [ + Address.fromString('0x00a4dfb447a43a583d8e07eae9d4efbb3656cbcb'), + Address.fromString('0xad4c666fc170b468b19988959eb931a3676f0e9f'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + ], + [ + Address.fromString('0xdeb1106b510d94df3bcc55e74f51a6f6b231d97e'), + Address.fromString('0x4983691a26d55eb9e18d2e12e3b770cdd3f76a5f'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xd2243a43813cd7c4bfb2287f32d3989b0f2f67d5'), + Address.fromString('0x8e2eaef2c05ef93f424a8324b94e725eaa362f91'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + ], + [ + Address.fromString('0x0b3a6896345b68539571aab140134630151ebc68'), + Address.fromString('0x8531e48a8611729185be9eaad945acbd6b32e256'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x4200000000000000000000000000000000000006'), + ], + [ + Address.fromString('0x99959743247f2fa2e97b33e532337eae616beeda'), + Address.fromString('0xeb1817b708415f4f78c5f0c99cbbd6a3a899fa6d'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x94ee41af02171d6dc1e05b790de547fa50dbd7cf'), + Address.fromString('0x26e7fed14a97e0c482a302237971cf1b04f6d3e9'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x7613311fbb6a4580cdd602f9978c317b2a783d5f'), + Address.fromString('0x3926a81afe5c9c3d05296e4fac4728ba5411ac78'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x89fe55759966831d747669bfbda477ebf09475d6'), + Address.fromString('0x7a5ea63fe3430a3b9a06fd80a4a9afaa17c1e878'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xB27E3Eab7526bF721ea8029bFcd3fDc94c4f8b5b'), + ], + [ + Address.fromString('0x1c536614fd8ed5faba94528782fbc886c426651a'), + Address.fromString('0xf5a389030a565c13d6e6bbe9342ac9d31dc7521a'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xe405de8f52ba7559f9df3c368500b6e6ae6cee49'), + ], + [ + Address.fromString('0xb0e9a44258cce8ef36c87e8f252aa6bf7cd4b245'), + Address.fromString('0x6168ec836d0b1f0c37381ec7ed1891a412872121'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0xcd7b42cee81a3394ee58dab93bbfc87cab03adb5'), + Address.fromString('0x2024c394741a5301e89a375b7bf52f865bc166fd'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0x88f8cd42570f74ff3ef5acd090419070c6efe37a'), + Address.fromString('0x91cca461ee9435848ac0da8fc416ad0816272786'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0xd4bbfe5b58381ba4b9ce87146ce9e5a2d1057d3e'), + Address.fromString('0x865d39d66dee5719e6bee98885ef40b9a36bf56e'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0x94b008aA00579c1307B0EF2c499aD98a8ce58e58'), + ], + [ + Address.fromString('0x9b8ad5085af53eff13f3ddadcafa453549f7a93f'), + Address.fromString('0x1fff624960ff9d0556420f3647d6aaf06389aab1'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0x188530f0c09e56e6e30dd5ef76a9b3f0dc403763'), + Address.fromString('0xc8c07386e29f3f239b91019d5426ae139c5bd17b'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x96db852D93c2feA0F447D6Ec22E146e4e09Caee6'), + ], + [ + Address.fromString('0x704baee64df71741cf3029652dc99101adc846f0'), + Address.fromString('0x1b19825a9e32b1039080acb1e1f9271314938b96'), + Address.fromString('0x7FB688CCf682d58f86D7e38e03f9D22e7705448B'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0xe4decbe898a6b8bb79ac48e93681cd04d7b1ca1b'), + Address.fromString('0x602a4d0f9e8d40ad3f620050efd1690da908dc0d'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x7FB688CCf682d58f86D7e38e03f9D22e7705448B'), + ], + [ + Address.fromString('0x251144c131413a5f6e54001cb586f9101b447059'), + Address.fromString('0x345ddb5743859efce0e6e8293ebd35373d34b6c7'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0xe405de8f52ba7559f9df3c368500b6e6ae6cee49'), + ], + [ + Address.fromString('0x4065c249115481baaec5c6a16929592935d29ec1'), + Address.fromString('0x94ad9a19126ebb02dda874237e5820fd4943f5de'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0x6c66eb2798bf42455b63cff3fa3e5bcc3d31848f'), + Address.fromString('0x905707e5c7a10e8351bbd03347be8b5f5de7301a'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + ], + [ + Address.fromString('0xa0eed53ea02a174e4ee81d88d3970b5198580b52'), + Address.fromString('0x7d1602f342787f80aef458c10e741149a1697447'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + ], + [ + Address.fromString('0xb61a5a79a83ff386dbe40a1bc95578856ab2fa5f'), + Address.fromString('0xa7bb0d95c6ba0ed0aca70c503b34bc7108589a47'), + Address.fromString('0x68f180fcCe6836688e9084f035309E29Bf0A2095'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0xc102e1de27d8467589cc65f4b4b18d534f6fdac6'), + Address.fromString('0xb0eca217602b031e03956553fb510085c9f2df28'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x8F69Ee043d52161Fd29137AeDf63f5e70cd504D5'), + ], + [ + Address.fromString('0x61057f7f7c2e338c36fd29433d7977b618348cd0'), + Address.fromString('0x320616dbe138aa2f3db7a5a46ba79a13032cc5f2'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0x05c1d7c9b9b4f1c38859681bd7b4eebb4c373a8e'), + Address.fromString('0xba213008fe93b3591e439f3b2aa51b3e4a2bd7c7'), + Address.fromString('0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + ], + [ + Address.fromString('0xbf592a3a4c64c8c28b667d060336e25480fe6c48'), + Address.fromString('0x680b4eb8b9b8533d503a545adad4af9f00df5f05'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7C17611Ed67D562D1F00ce82eebD39Cb7B595472'), + ], + [ + Address.fromString('0xb2ab739b499ff9fa019ff944135b4974942b3a95'), + Address.fromString('0x296b88b607ea3a03c821ca4dc34dd9e7e4efa041'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7FB688CCf682d58f86D7e38e03f9D22e7705448B'), + ], + [ + Address.fromString('0x3e9ef76529932226742113984e6a6c7cea7e2452'), + Address.fromString('0xa99638e4ac81d4ce32c945c1415f89ab8d86bf2c'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x8c6f28f2F1A3C87F0f938b96d27520d9751ec8d9'), + ], + [ + Address.fromString('0xcb590932a77e02aac00c83bbba4d8014efbebb89'), + Address.fromString('0x9bb3267c4c3e69a961479c475f8fcc4c300af5bd'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x7FB688CCf682d58f86D7e38e03f9D22e7705448B'), + ], + [ + Address.fromString('0x3643c5840fc0ccf4f667a35a151e10302d4d0d23'), + Address.fromString('0x65f8a80d8049a77619435f841055fa4c8d785c47'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0x96db852D93c2feA0F447D6Ec22E146e4e09Caee6'), + ], + [ + Address.fromString('0x805b9cf595282d807adfe84a89bec85be5d07f53'), + Address.fromString('0xd3265ea86af798659b4132a453e7cdb29b877e10'), + Address.fromString('0x96db852D93c2feA0F447D6Ec22E146e4e09Caee6'), + Address.fromString('0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1'), + ], + [ + Address.fromString('0x1a718270a5b014209fb77ac2985556ee471b29af'), + Address.fromString('0x8dfc59e8b119bffa5f552642028e005b1972edc4'), + Address.fromString('0x6fd9d7AD17242c41f7131d257212c54A0e816691'), + Address.fromString('0x96db852D93c2feA0F447D6Ec22E146e4e09Caee6'), + ], + [ + Address.fromString('0xb91cf01b64c6e6540c45ae356554599cbe92831f'), + Address.fromString('0xc210aeb4e84e0c3b6ee5816858984d52d04f0219'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x96db852D93c2feA0F447D6Ec22E146e4e09Caee6'), + ], + [ + Address.fromString('0x8956827b23063c82d0c697004f0015b454a2f107'), + Address.fromString('0x9aaa481a863e95168c01f23640b357b014dff09a'), + Address.fromString('0x7F5c764cBc14f9669B88837ca1490cCa17c31607'), + Address.fromString('0x8700dAec35aF8Ff88c16BdF0418774CB3D7599B4'), + ], + [ + Address.fromString('0x86cf7e458ce79afe44924263d58ef1fd57d1b57c'), + Address.fromString('0x25cc77a38f8de3b9b090fea8f0f5995c4e10a386'), + Address.fromString('0x4200000000000000000000000000000000000006'), + Address.fromString('0xe0BB0D3DE8c10976511e5030cA403dBf4c25165B'), + ], +] diff --git a/src/mappings/factory.ts b/src/mappings/factory.ts index ab2cc02c..c7d7d6ee 100644 --- a/src/mappings/factory.ts +++ b/src/mappings/factory.ts @@ -1,13 +1,13 @@ -import { Address, BigInt, log } from '@graphprotocol/graph-ts' +import { BigInt, log } from '@graphprotocol/graph-ts' +import { populateEmptyPools } from '../backfill' import { PoolCreated } from '../types/Factory/Factory' import { Factory } from '../types/schema' import { Bundle, Pool, Token } from '../types/schema' import { Pool as PoolTemplate } from '../types/templates' -import { STATIC_TOKEN_DEFINITIONS, StaticTokenDefinition } from '../utils/staticTokenDefinition' +import { getSubgraphConfig, SubgraphConfig } from '../utils/chains' import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from '../utils/token' -import { ADDRESS_ZERO, FACTORY_ADDRESS, ONE_BI, ZERO_BD, ZERO_BI } from './../utils/constants' -import { WHITELIST_TOKENS } from './../utils/pricing' +import { ADDRESS_ZERO, ONE_BI, ZERO_BD, ZERO_BI } from './../utils/constants' // The subgraph handler must have this signature to be able to handle events, // however, we invoke a helper in order to inject dependencies for unit tests. @@ -18,12 +18,16 @@ export function handlePoolCreated(event: PoolCreated): void { // Exported for unit tests export function handlePoolCreatedHelper( event: PoolCreated, - factoryAddress: string = FACTORY_ADDRESS, - whitelistTokens: string[] = WHITELIST_TOKENS, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, + subgraphConfig: SubgraphConfig = getSubgraphConfig(), ): void { + const factoryAddress = subgraphConfig.factoryAddress + const whitelistTokens = subgraphConfig.whitelistTokens + const tokenOverrides = subgraphConfig.tokenOverrides + const poolsToSkip = subgraphConfig.poolsToSkip + const poolMappings = subgraphConfig.poolMappings + // temp fix - if (event.params.pool == Address.fromHexString('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248')) { + if (poolsToSkip.includes(event.params.pool.toHexString())) { return } @@ -48,6 +52,8 @@ export function handlePoolCreatedHelper( const bundle = new Bundle('1') bundle.ethPriceUSD = ZERO_BD bundle.save() + + populateEmptyPools(event, poolMappings, whitelistTokens, tokenOverrides) } factory.poolCount = factory.poolCount.plus(ONE_BI) @@ -59,10 +65,10 @@ export function handlePoolCreatedHelper( // fetch info if null if (token0 === null) { token0 = new Token(event.params.token0.toHexString()) - token0.symbol = fetchTokenSymbol(event.params.token0, staticTokenDefinitions) - token0.name = fetchTokenName(event.params.token0, staticTokenDefinitions) + token0.symbol = fetchTokenSymbol(event.params.token0, tokenOverrides) + token0.name = fetchTokenName(event.params.token0, tokenOverrides) token0.totalSupply = fetchTokenTotalSupply(event.params.token0) - const decimals = fetchTokenDecimals(event.params.token0, staticTokenDefinitions) + const decimals = fetchTokenDecimals(event.params.token0, tokenOverrides) // bail if we couldn't figure out the decimals if (decimals === null) { @@ -86,10 +92,10 @@ export function handlePoolCreatedHelper( if (token1 === null) { token1 = new Token(event.params.token1.toHexString()) - token1.symbol = fetchTokenSymbol(event.params.token1) - token1.name = fetchTokenName(event.params.token1) + token1.symbol = fetchTokenSymbol(event.params.token1, tokenOverrides) + token1.name = fetchTokenName(event.params.token1, tokenOverrides) token1.totalSupply = fetchTokenTotalSupply(event.params.token1) - const decimals = fetchTokenDecimals(event.params.token1) + const decimals = fetchTokenDecimals(event.params.token1, tokenOverrides) // bail if we couldn't figure out the decimals if (decimals === null) { log.debug('mybug the decimal on token 0 was null', []) diff --git a/src/mappings/pool/burn.ts b/src/mappings/pool/burn.ts index 3f924c6c..58ca1cbc 100644 --- a/src/mappings/pool/burn.ts +++ b/src/mappings/pool/burn.ts @@ -3,7 +3,8 @@ import { BigInt } from '@graphprotocol/graph-ts' import { Bundle, Burn, Factory, Pool, Tick, Token } from '../../types/schema' import { Burn as BurnEvent } from '../../types/templates/Pool/Pool' import { convertTokenToDecimal, loadTransaction } from '../../utils' -import { FACTORY_ADDRESS, ONE_BI } from '../../utils/constants' +import { getSubgraphConfig, SubgraphConfig } from '../../utils/chains' +import { ONE_BI } from '../../utils/constants' import { updatePoolDayData, updatePoolHourData, @@ -17,7 +18,9 @@ export function handleBurn(event: BurnEvent): void { } // Note: this handler need not adjust TVL because that is accounted for in the handleCollect handler -export function handleBurnHelper(event: BurnEvent, factoryAddress: string = FACTORY_ADDRESS): void { +export function handleBurnHelper(event: BurnEvent, subgraphConfig: SubgraphConfig = getSubgraphConfig()): void { + const factoryAddress = subgraphConfig.factoryAddress + const bundle = Bundle.load('1')! const poolAddress = event.address.toHexString() const pool = Pool.load(poolAddress)! @@ -91,7 +94,7 @@ export function handleBurnHelper(event: BurnEvent, factoryAddress: string = FACT lowerTick.save() upperTick.save() } - updateUniswapDayData(event) + updateUniswapDayData(event, factoryAddress) updatePoolDayData(event) updatePoolHourData(event) updateTokenDayData(token0 as Token, event) diff --git a/src/mappings/pool/collect.ts b/src/mappings/pool/collect.ts index 6cbf87a4..89417947 100644 --- a/src/mappings/pool/collect.ts +++ b/src/mappings/pool/collect.ts @@ -3,7 +3,8 @@ 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 { getSubgraphConfig, SubgraphConfig } from '../../utils/chains' +import { ONE_BI } from '../../utils/constants' import { updatePoolDayData, updatePoolHourData, @@ -11,17 +12,16 @@ import { updateTokenHourData, updateUniswapDayData, } from '../../utils/intervalUpdates' -import { getTrackedAmountUSD, WHITELIST_TOKENS } from '../../utils/pricing' +import { getTrackedAmountUSD } from '../../utils/pricing' export function handleCollect(event: CollectEvent): void { handleCollectHelper(event) } -export function handleCollectHelper( - event: CollectEvent, - factoryAddress: string = FACTORY_ADDRESS, - whitelistTokens: string[] = WHITELIST_TOKENS, -): void { +export function handleCollectHelper(event: CollectEvent, subgraphConfig: SubgraphConfig = getSubgraphConfig()): void { + const factoryAddress = subgraphConfig.factoryAddress + const whitelistTokens = subgraphConfig.whitelistTokens + const bundle = Bundle.load('1')! const pool = Pool.load(event.address.toHexString()) if (pool == null) { @@ -92,7 +92,7 @@ export function handleCollectHelper( collect.tickUpper = BigInt.fromI32(event.params.tickUpper) collect.logIndex = event.logIndex - updateUniswapDayData(event) + updateUniswapDayData(event, factoryAddress) updatePoolDayData(event) updatePoolHourData(event) updateTokenDayData(token0 as Token, event) diff --git a/src/mappings/pool/initialize.ts b/src/mappings/pool/initialize.ts index 3e7c56a0..01cbd1a0 100644 --- a/src/mappings/pool/initialize.ts +++ b/src/mappings/pool/initialize.ts @@ -1,30 +1,22 @@ -import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' +import { BigInt } from '@graphprotocol/graph-ts' import { Bundle, Pool, Token } from '../../types/schema' import { Initialize } from '../../types/templates/Pool/Pool' +import { getSubgraphConfig, SubgraphConfig } from '../../utils/chains' import { updatePoolDayData, updatePoolHourData } from '../../utils/intervalUpdates' -import { - findEthPerToken, - getEthPriceInUSD, - MINIMUM_ETH_LOCKED, - STABLE_COINS, - STABLECOIN_IS_TOKEN0, - USDC_WETH_03_POOL, - WETH_ADDRESS, -} from '../../utils/pricing' +import { findNativePerToken, getNativePriceInUSD } from '../../utils/pricing' export function handleInitialize(event: Initialize): void { handleInitializeHelper(event) } -export function handleInitializeHelper( - event: Initialize, - stablecoinWrappedNativePoolAddress: string = USDC_WETH_03_POOL, - stablecoinIsToken0: boolean = STABLECOIN_IS_TOKEN0, - wrappedNativeAddress: string = WETH_ADDRESS, - stablecoinAddresses: string[] = STABLE_COINS, - minimumEthLocked: BigDecimal = MINIMUM_ETH_LOCKED, -): void { +export function handleInitializeHelper(event: Initialize, subgraphConfig: SubgraphConfig = getSubgraphConfig()): void { + const stablecoinWrappedNativePoolAddress = subgraphConfig.stablecoinWrappedNativePoolAddress + const stablecoinIsToken0 = subgraphConfig.stablecoinIsToken0 + const wrappedNativeAddress = subgraphConfig.wrappedNativeAddress + const stablecoinAddresses = subgraphConfig.stablecoinAddresses + const minimumNativeLocked = subgraphConfig.minimumNativeLocked + // update pool sqrt price and tick const pool = Pool.load(event.address.toHexString())! pool.sqrtPrice = event.params.sqrtPriceX96 @@ -37,7 +29,7 @@ export function handleInitializeHelper( // update ETH price now that prices could have changed const bundle = Bundle.load('1')! - bundle.ethPriceUSD = getEthPriceInUSD(stablecoinWrappedNativePoolAddress, stablecoinIsToken0) + bundle.ethPriceUSD = getNativePriceInUSD(stablecoinWrappedNativePoolAddress, stablecoinIsToken0) bundle.save() updatePoolDayData(event) @@ -45,8 +37,18 @@ export function handleInitializeHelper( // update token prices if (token0 && token1) { - token0.derivedETH = findEthPerToken(token0 as Token, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) - token1.derivedETH = findEthPerToken(token1 as Token, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) + token0.derivedETH = findNativePerToken( + token0 as Token, + wrappedNativeAddress, + stablecoinAddresses, + minimumNativeLocked, + ) + token1.derivedETH = findNativePerToken( + token1 as Token, + wrappedNativeAddress, + stablecoinAddresses, + minimumNativeLocked, + ) token0.save() token1.save() } diff --git a/src/mappings/pool/mint.ts b/src/mappings/pool/mint.ts index a71dcf24..d3598368 100644 --- a/src/mappings/pool/mint.ts +++ b/src/mappings/pool/mint.ts @@ -3,7 +3,8 @@ import { BigInt } from '@graphprotocol/graph-ts' import { Bundle, Factory, Mint, Pool, Tick, Token } from '../../types/schema' import { Mint as MintEvent } from '../../types/templates/Pool/Pool' import { convertTokenToDecimal, loadTransaction } from '../../utils' -import { FACTORY_ADDRESS, ONE_BI } from '../../utils/constants' +import { getSubgraphConfig, SubgraphConfig } from '../../utils/chains' +import { ONE_BI } from '../../utils/constants' import { updatePoolDayData, updatePoolHourData, @@ -17,7 +18,9 @@ export function handleMint(event: MintEvent): void { handleMintHelper(event) } -export function handleMintHelper(event: MintEvent, factoryAddress: string = FACTORY_ADDRESS): void { +export function handleMintHelper(event: MintEvent, subgraphConfig: SubgraphConfig = getSubgraphConfig()): void { + const factoryAddress = subgraphConfig.factoryAddress + const bundle = Bundle.load('1')! const poolAddress = event.address.toHexString() const pool = Pool.load(poolAddress)! @@ -122,7 +125,7 @@ export function handleMintHelper(event: MintEvent, factoryAddress: string = FACT // TODO: Update Tick's volume, fees, and liquidity provider count. Computing these on the tick // level requires reimplementing some of the swapping code from v3-core. - updateUniswapDayData(event) + updateUniswapDayData(event, factoryAddress) updatePoolDayData(event) updatePoolHourData(event) updateTokenDayData(token0 as Token, event) diff --git a/src/mappings/pool/swap.ts b/src/mappings/pool/swap.ts index 45458c2d..3bf27c74 100644 --- a/src/mappings/pool/swap.ts +++ b/src/mappings/pool/swap.ts @@ -3,7 +3,8 @@ import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' import { Bundle, Factory, Pool, Swap, Token } from '../../types/schema' import { Swap as SwapEvent } from '../../types/templates/Pool/Pool' import { convertTokenToDecimal, loadTransaction, safeDiv } from '../../utils' -import { FACTORY_ADDRESS, ONE_BI, ZERO_BD } from '../../utils/constants' +import { getSubgraphConfig, SubgraphConfig } from '../../utils/chains' +import { ONE_BI, ZERO_BD } from '../../utils/constants' import { updatePoolDayData, updatePoolHourData, @@ -12,33 +13,27 @@ import { updateUniswapDayData, } from '../../utils/intervalUpdates' import { - findEthPerToken, - getEthPriceInUSD, + findNativePerToken, + getNativePriceInUSD, getTrackedAmountUSD, - MINIMUM_ETH_LOCKED, sqrtPriceX96ToTokenPrices, - STABLE_COINS, - STABLECOIN_IS_TOKEN0, - USDC_WETH_03_POOL, - WETH_ADDRESS, - WHITELIST_TOKENS, } from '../../utils/pricing' export function handleSwap(event: SwapEvent): void { handleSwapHelper(event) } -export function handleSwapHelper( - event: SwapEvent, - stablecoinWrappedNativePoolAddress: string = USDC_WETH_03_POOL, - stablecoinIsToken0: boolean = STABLECOIN_IS_TOKEN0, - wrappedNativeAddress: string = WETH_ADDRESS, - stablecoinAddresses: string[] = STABLE_COINS, - minimumEthLocked: BigDecimal = MINIMUM_ETH_LOCKED, - whitelistTokens: string[] = WHITELIST_TOKENS, -): void { +export function handleSwapHelper(event: SwapEvent, subgraphConfig: SubgraphConfig = getSubgraphConfig()): void { + const factoryAddress = subgraphConfig.factoryAddress + const stablecoinWrappedNativePoolAddress = subgraphConfig.stablecoinWrappedNativePoolAddress + const stablecoinIsToken0 = subgraphConfig.stablecoinIsToken0 + const wrappedNativeAddress = subgraphConfig.wrappedNativeAddress + const stablecoinAddresses = subgraphConfig.stablecoinAddresses + const minimumNativeLocked = subgraphConfig.minimumNativeLocked + const whitelistTokens = subgraphConfig.whitelistTokens + const bundle = Bundle.load('1')! - const factory = Factory.load(FACTORY_ADDRESS)! + const factory = Factory.load(factoryAddress)! const pool = Pool.load(event.address.toHexString())! // hot fix for bad pricing @@ -133,10 +128,20 @@ export function handleSwapHelper( pool.save() // update USD pricing - bundle.ethPriceUSD = getEthPriceInUSD(stablecoinWrappedNativePoolAddress, stablecoinIsToken0) + bundle.ethPriceUSD = getNativePriceInUSD(stablecoinWrappedNativePoolAddress, stablecoinIsToken0) bundle.save() - token0.derivedETH = findEthPerToken(token0 as Token, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) - token1.derivedETH = findEthPerToken(token1 as Token, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) + token0.derivedETH = findNativePerToken( + token0 as Token, + wrappedNativeAddress, + stablecoinAddresses, + minimumNativeLocked, + ) + token1.derivedETH = findNativePerToken( + token1 as Token, + wrappedNativeAddress, + stablecoinAddresses, + minimumNativeLocked, + ) /** * Things afffected by new USD rates @@ -171,7 +176,7 @@ export function handleSwapHelper( swap.logIndex = event.logIndex // interval data - const uniswapDayData = updateUniswapDayData(event) + const uniswapDayData = updateUniswapDayData(event, factoryAddress) const poolDayData = updatePoolDayData(event) const poolHourData = updatePoolHourData(event) const token0DayData = updateTokenDayData(token0 as Token, event) diff --git a/src/utils/chains.ts b/src/utils/chains.ts new file mode 100644 index 00000000..84b6f35c --- /dev/null +++ b/src/utils/chains.ts @@ -0,0 +1,361 @@ +import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' + +import { StaticTokenDefinition } from './staticTokenDefinition' + +export enum ChainId { + ARBITRUM_ONE = 42161, + AVALANCHE = 43114, + BASE = 8453, + BLAST_MAINNET = 81457, + BSC = 56, + CELO = 42220, + MAINNET = 1, + MATIC = 137, + OPTIMISM = 10, +} + +// Note: All token and pool addresses should be lowercased! +export class SubgraphConfig { + // deployment address + // e.g. https://docs.uniswap.org/contracts/v3/reference/deployments/ethereum-deployments + factoryAddress: string + + // the address of a pool where one token is a stablecoin and the other is a + // token that tracks the price of the native token use this to calculate the + // price of the native token, so prefer a pool with highest liquidity + stablecoinWrappedNativePoolAddress: string + + // true is stablecoin is token0, false if stablecoin is token1 + stablecoinIsToken0: boolean + + // the address of a token that tracks the price of the native token, most of + // the time, this is a wrapped asset but could also be the native token itself + // for some chains + wrappedNativeAddress: string + + // the mimimum liquidity in a pool needed for it to be used to help calculate + // token prices. for new chains, this should be initialized to ~4000 USD + minimumNativeLocked: BigDecimal + + // list of stablecoin addresses + stablecoinAddresses: string[] + + // a token must be in a pool with one of these tokens in order to derive a + // price (in addition to passing the minimumEthLocked check). This is also + // used to determine whether volume is tracked or not. + whitelistTokens: string[] + + // token overrides are used to override RPC calls for the symbol, name, and + // decimals for tokens. for new chains this is typically empty. + tokenOverrides: StaticTokenDefinition[] + + // skip the creation of these pools in handlePoolCreated. for new chains this is typically empty. + poolsToSkip: string[] + + // initialize this list of pools and token addresses on factory creation. for new chains this is typically empty. + poolMappings: Array +} + +export function getSubgraphConfig(): SubgraphConfig { + // Update this value to the corresponding chain you want to deploy + const SELECTED_CHAIN = ChainId.BASE + + switch (SELECTED_CHAIN) { + case ChainId.ARBITRUM_ONE: { + return { + factoryAddress: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + stablecoinWrappedNativePoolAddress: '0x17c14d2c404d167802b16c450d3c99f88f2c4f4d', // WETH-USDC 0.3% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', // WETH + minimumNativeLocked: BigDecimal.fromString('20'), + stablecoinAddresses: [ + '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', // USDC + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', // DAI + '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', // USDT + ], + whitelistTokens: [ + '0x82af49447d8a07e3bd95bd0d56f35241523fbab1', // WETH + '0xff970a61a04b1ca14834a43f5de4533ebddb5cc8', // USDC + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', // DAI + '0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9', // USDT + ], + tokenOverrides: [ + { + address: Address.fromString('0x82af49447d8a07e3bd95bd0d56f35241523fbab1'), + symbol: 'WETH', + name: 'Wrapped Ethereum', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0xff970a61a04b1ca14834a43f5de4533ebddb5cc8'), + symbol: 'USDC', + name: 'USD Coin', + decimals: BigInt.fromI32(6), + }, + ], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.AVALANCHE: { + return { + factoryAddress: '0x740b1c1de25031C31FF4fC9A62f554A55cdC1baD', + stablecoinWrappedNativePoolAddress: '0xfae3f424a0a47706811521e3ee268f00cfb5c45e', // WAVAX-USDC 0.05% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', // WAVAX + minimumNativeLocked: BigDecimal.fromString('1000'), + stablecoinAddresses: [ + '0xd586e7f844cea2f87f50152665bcbc2c279d8d70', // DAI_E + '0xba7deebbfc5fa1100fb055a87773e1e99cd3507a', // DAI + '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664', // USDC_E + '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', // USDC + '0xc7198437980c041c805a1edcba50c1ce5db95118', // USDT_E + '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', // USDT + ], + whitelistTokens: [ + '0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7', // WAVAX + '0xd586e7f844cea2f87f50152665bcbc2c279d8d70', // DAI_E + '0xba7deebbfc5fa1100fb055a87773e1e99cd3507a', // DAI + '0xa7d7079b0fead91f3e65f86e8915cb59c1a4c664', // USDC_E + '0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e', // USDC + '0xc7198437980c041c805a1edcba50c1ce5db95118', // USDT_E + '0x9702230a8ea53601f5cd2dc00fdbc13d4df4a8c7', // USDT + '0x130966628846bfd36ff31a822705796e8cb8c18d', // MIM + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.BASE: { + return { + factoryAddress: '0x33128a8fC17869897dcE68Ed026d694621f6FDfD', + stablecoinWrappedNativePoolAddress: '0x4c36388be6f416a29c8d8eee81c771ce6be14b18', // WETH-USDbC 0.05% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0x4200000000000000000000000000000000000006', // WETH + minimumNativeLocked: BigDecimal.fromString('1'), + stablecoinAddresses: [ + '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // USDC + ], + whitelistTokens: [ + '0x4200000000000000000000000000000000000006', // WETH + '0x833589fcd6edb6e08f4c7c32d4f71b54bda02913', // USDC + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.BLAST_MAINNET: { + return { + factoryAddress: '0x792edAdE80af5fC680d96a2eD80A44247D2Cf6Fd', + stablecoinWrappedNativePoolAddress: '0xf52b4b69123cbcf07798ae8265642793b2e8990c', // USDB-WETH 0.3% pool + stablecoinIsToken0: true, + wrappedNativeAddress: '0x4300000000000000000000000000000000000004', // WETH + minimumNativeLocked: BigDecimal.fromString('1'), + stablecoinAddresses: [ + '0x4300000000000000000000000000000000000003', // USDB + ], + whitelistTokens: [ + '0x4300000000000000000000000000000000000004', // WETH + '0x4300000000000000000000000000000000000003', // USDB + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.BSC: { + return { + factoryAddress: '0xdB1d10011AD0Ff90774D0C6Bb92e5C5c8b4461F7', + stablecoinWrappedNativePoolAddress: '0x6fe9e9de56356f7edbfcbb29fab7cd69471a4869', // USDC-WBNB 0.3% pool + stablecoinIsToken0: true, + wrappedNativeAddress: '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', // WBNB + minimumNativeLocked: BigDecimal.fromString('100'), + stablecoinAddresses: [ + '0x55d398326f99059ff775485246999027b3197955', // USDT + '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC + ], + whitelistTokens: [ + '0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c', // WBNB + '0x55d398326f99059ff775485246999027b3197955', // USDT + '0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d', // USDC + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.CELO: { + return { + factoryAddress: '0xAfE208a311B21f13EF87E33A90049fC17A7acDEc', + stablecoinWrappedNativePoolAddress: '0x2d70cbabf4d8e61d5317b62cbe912935fd94e0fe', // CUSD-CELO 0.01% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0x471ece3750da237f93b8e339c536989b8978a438', // CELO + minimumNativeLocked: BigDecimal.fromString('3600'), + stablecoinAddresses: [ + '0x765de816845861e75a25fca122bb6898b8b1282a', // CUSD + '0xef4229c8c3250c675f21bcefa42f58efbff6002a', // Bridged USDC + '0xceba9300f2b948710d2653dd7b07f33a8b32118c', // Native USDC + ], + whitelistTokens: [ + '0x471ece3750da237f93b8e339c536989b8978a438', // CELO + '0x765de816845861e75a25fca122bb6898b8b1282a', // CUSD + '0xef4229c8c3250c675f21bcefa42f58efbff6002a', // Bridged USDC + '0xceba9300f2b948710d2653dd7b07f33a8b32118c', // Native USDC + '0xd8763cba276a3738e6de85b4b3bf5fded6d6ca73', // CEUR + '0xe8537a3d056da446677b9e9d6c5db704eaab4787', // CREAL + '0x46c9757c5497c5b1f2eb73ae79b6b67d119b0b58', // PACT + '0x17700282592d6917f6a73d0bf8accf4d578c131e', // MOO + '0x66803fb87abd4aac3cbb3fad7c3aa01f6f3fb207', // Portal Eth + '0xbaab46e28388d2779e6e31fd00cf0e5ad95e327b', // WBTC + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + } + case ChainId.MAINNET: { + return { + factoryAddress: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + stablecoinWrappedNativePoolAddress: '0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8', // USDC-WETH 0.3% pool + stablecoinIsToken0: true, + wrappedNativeAddress: '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH + minimumNativeLocked: BigDecimal.fromString('20'), + stablecoinAddresses: [ + '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC + '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT + '0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD + '0x956f47f50a910163d8bf957cf5846d573e7f87ca', // FEI + ], + whitelistTokens: [ + '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2', // WETH + '0x6b175474e89094c44da98b954eedeac495271d0f', // DAI + '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC + '0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT + '0x0000000000085d4780b73119b644ae5ecd22b376', // TUSD + '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599', // WBTC + '0x5d3a536e4d6dbd6114cc1ead35777bab948e3643', // cDAI + '0x39aa39c021dfbae8fac545936693ac917d5e7563', // cUSDC + '0x86fadb80d8d2cff3c3680819e4da99c10232ba0f', // EBASE + '0x57ab1ec28d129707052df4df418d58a2d46d5f51', // sUSD + '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', // MKR + '0xc00e94cb662c3520282e6f5717214004a7f26888', // COMP + '0x514910771af9ca656af840dff83e8264ecf986ca', // LINK + '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f', // SNX + '0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e', // YFI + '0x111111111117dc0aa78b770fa6a738034120c302', // 1INCH + '0xdf5e0e81dff6faf3a7e52ba697820c5e32d806a8', // yCurv + '0x956f47f50a910163d8bf957cf5846d573e7f87ca', // FEI + '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', // MATIC + '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', // AAVE + '0xfe2e637202056d30016725477c5da089ab0a043a', // sETH2 + ], + tokenOverrides: [ + { + address: Address.fromString('0xe0b7927c4af23765cb51314a0e0521a9645f0e2a'), + symbol: 'DGD', + name: 'DGD', + decimals: BigInt.fromI32(9), + }, + { + address: Address.fromString('0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9'), + symbol: 'AAVE', + name: 'Aave Token', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0xeb9951021698b42e4399f9cbb6267aa35f82d59d'), + symbol: 'LIF', + name: 'Lif', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0xbdeb4b83251fb146687fa19d1c660f99411eefe3'), + symbol: 'SVD', + name: 'savedroid', + decimals: BigInt.fromI32(18), + }, + { + address: Address.fromString('0xbb9bc244d798123fde783fcc1c72d3bb8c189413'), + symbol: 'TheDAO', + name: 'TheDAO', + decimals: BigInt.fromI32(16), + }, + { + address: Address.fromString('0x38c6a68304cdefb9bec48bbfaaba5c5b47818bb2'), + symbol: 'HPB', + name: 'HPBCoin', + decimals: BigInt.fromI32(18), + }, + ], + poolsToSkip: ['0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248'], + poolMappings: [], + } + } + case ChainId.MATIC: + return { + factoryAddress: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + stablecoinWrappedNativePoolAddress: '0xa374094527e1673a86de625aa59517c5de346d32', // WMATIC-USDC 0.05% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', // WMATIC + minimumNativeLocked: BigDecimal.fromString('20000'), + stablecoinAddresses: [ + '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', // USDC + '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063', // DAI + ], + whitelistTokens: [ + '0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270', // WMATIC + '0x7ceb23fd6bc0add59e62ac25578270cff1b9f619', // WETH + '0x2791bca1f2de4661ed88a30c99a7a9449aa84174', // USDC + '0x8f3cf7ad23cd3cadbd9735aff958023239c6a063', // DAI + ], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], + } + case ChainId.OPTIMISM: { + return { + factoryAddress: '0x1F98431c8aD98523631AE4a59f267346ea31F984', + stablecoinWrappedNativePoolAddress: '0x03af20bdaaffb4cc0a521796a223f7d85e2aac31', // DAI-WETH 0.3% pool + stablecoinIsToken0: false, + wrappedNativeAddress: '0x4200000000000000000000000000000000000006', // WETH + minimumNativeLocked: BigDecimal.fromString('10'), + stablecoinAddresses: [ + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', // DAI + '0x7f5c764cbc14f9669b88837ca1490cca17c31607', // USDC + '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', // USDT + ], + whitelistTokens: [ + '0x4200000000000000000000000000000000000006', // WETH + '0xda10009cbd5d07dd0cecc66161fc93d7c9000da1', // DAI + '0x7f5c764cbc14f9669b88837ca1490cca17c31607', // USDC + '0x94b008aa00579c1307b0ef2c499ad98a8ce58e58', // USDT + '0x4200000000000000000000000000000000000042', // OP + '0x9e1028f5f1d5ede59748ffcee5532509976840e0', // PERP + '0x50c5725949a6f0c72e6c4a641f24049a917db0cb', // LYRA + '0x68f180fcce6836688e9084f035309e29bf0a2095', // WBTC + ], + tokenOverrides: [ + { + address: Address.fromString('0x82af49447d8a07e3bd95bd0d56f35241523fbab1'), + symbol: 'WETH', + name: 'Wrapped Ethereum', + decimals: BigInt.fromI32(18), + }, + ], + poolsToSkip: [ + '0x282b7d6bef6c78927f394330dca297eca2bd18cd', + '0x5738de8d0b864d5ef5d65b9e05b421b71f2c2eb4', + '0x5500721e5a063f0396c5e025a640e8491eb89aac', + '0x1ffd370f9d01f75de2cc701956886acec9749e80', + ], + poolMappings: [], + } + } + + default: + throw new Error('Unsupported chain ID') + } +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts index 6c578871..a087af78 100644 --- a/src/utils/constants.ts +++ b/src/utils/constants.ts @@ -1,14 +1,9 @@ -import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' - -import { Factory as FactoryContract } from '../types/templates/Pool/Factory' +import { BigDecimal, BigInt } from '@graphprotocol/graph-ts' export const ADDRESS_ZERO = '0x0000000000000000000000000000000000000000' -export const FACTORY_ADDRESS = '0x1F98431c8aD98523631AE4a59f267346ea31F984' export const ZERO_BI = BigInt.fromI32(0) export const ONE_BI = BigInt.fromI32(1) export const ZERO_BD = BigDecimal.fromString('0') export const ONE_BD = BigDecimal.fromString('1') export const BI_18 = BigInt.fromI32(18) - -export const factoryContract = FactoryContract.bind(Address.fromString(FACTORY_ADDRESS)) diff --git a/src/utils/intervalUpdates.ts b/src/utils/intervalUpdates.ts index 2d2232b0..ccbb2f71 100644 --- a/src/utils/intervalUpdates.ts +++ b/src/utils/intervalUpdates.ts @@ -12,13 +12,12 @@ import { UniswapDayData, } from './../types/schema' import { ONE_BI, ZERO_BD, ZERO_BI } from './constants' -import { FACTORY_ADDRESS } from './constants' /** * Tracks global aggregate data over daily windows * @param event */ -export function updateUniswapDayData(event: ethereum.Event, factoryAddress: string = FACTORY_ADDRESS): UniswapDayData { +export function updateUniswapDayData(event: ethereum.Event, factoryAddress: string): UniswapDayData { const uniswap = Factory.load(factoryAddress)! const timestamp = event.block.timestamp.toI32() const dayID = timestamp / 86400 // rounded diff --git a/src/utils/pricing.ts b/src/utils/pricing.ts index 6b834ff2..c5a9031c 100644 --- a/src/utils/pricing.ts +++ b/src/utils/pricing.ts @@ -55,9 +55,9 @@ export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, t return [price0, price1] } -export function getEthPriceInUSD( - stablecoinWrappedNativePoolAddress: string = USDC_WETH_03_POOL, - stablecoinIsToken0: boolean = STABLECOIN_IS_TOKEN0, // true is stablecoin is token0, false if stablecoin is token1 +export function getNativePriceInUSD( + stablecoinWrappedNativePoolAddress: string, + stablecoinIsToken0: boolean, ): BigDecimal { const stablecoinWrappedNativePool = Pool.load(stablecoinWrappedNativePoolAddress) if (stablecoinWrappedNativePool !== null) { @@ -71,11 +71,11 @@ export function getEthPriceInUSD( * Search through graph to find derived Eth per token. * @todo update to be derived ETH (add stablecoin estimates) **/ -export function findEthPerToken( +export function findNativePerToken( token: Token, - wrappedNativeAddress: string = WETH_ADDRESS, - stablecoinAddresses: string[] = STABLE_COINS, - minimumEthLocked: BigDecimal = MINIMUM_ETH_LOCKED, + wrappedNativeAddress: string, + stablecoinAddresses: string[], + minimumNativeLocked: BigDecimal, ): BigDecimal { if (token.id == wrappedNativeAddress) { return ONE_BD @@ -104,7 +104,7 @@ export function findEthPerToken( // get the derived ETH in pool if (token1) { const ethLocked = pool.totalValueLockedToken1.times(token1.derivedETH) - if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumEthLocked)) { + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumNativeLocked)) { largestLiquidityETH = ethLocked // token1 per our token * Eth per token1 priceSoFar = pool.token1Price.times(token1.derivedETH as BigDecimal) @@ -116,7 +116,7 @@ export function findEthPerToken( // get the derived ETH in pool if (token0) { const ethLocked = pool.totalValueLockedToken0.times(token0.derivedETH) - if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumEthLocked)) { + if (ethLocked.gt(largestLiquidityETH) && ethLocked.gt(minimumNativeLocked)) { largestLiquidityETH = ethLocked // token0 per our token * ETH per token0 priceSoFar = pool.token0Price.times(token0.derivedETH as BigDecimal) @@ -141,7 +141,7 @@ export function getTrackedAmountUSD( token0: Token, tokenAmount1: BigDecimal, token1: Token, - whitelistTokens: string[] = WHITELIST_TOKENS, + whitelistTokens: string[], ): BigDecimal { const bundle = Bundle.load('1')! const price0USD = token0.derivedETH.times(bundle.ethPriceUSD) diff --git a/src/utils/token.ts b/src/utils/token.ts index 1aca8117..5689bd22 100644 --- a/src/utils/token.ts +++ b/src/utils/token.ts @@ -4,12 +4,15 @@ import { ERC20 } from '../types/Factory/ERC20' import { ERC20NameBytes } from '../types/Factory/ERC20NameBytes' import { ERC20SymbolBytes } from '../types/Factory/ERC20SymbolBytes' import { isNullEthValue } from '.' -import { getStaticDefinition, STATIC_TOKEN_DEFINITIONS, StaticTokenDefinition } from './staticTokenDefinition' +import { getStaticDefinition, StaticTokenDefinition } from './staticTokenDefinition' + +export function fetchTokenSymbol(tokenAddress: Address, tokenOverrides: StaticTokenDefinition[]): string { + // try with the static definition + const staticTokenDefinition = getStaticDefinition(tokenAddress, tokenOverrides) + if (staticTokenDefinition != null) { + return staticTokenDefinition.symbol + } -export function fetchTokenSymbol( - tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, -): string { const contract = ERC20.bind(tokenAddress) const contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress) @@ -18,16 +21,10 @@ export function fetchTokenSymbol( const symbolResult = contract.try_symbol() if (symbolResult.reverted) { const symbolResultBytes = contractSymbolBytes.try_symbol() - if (!symbolResultBytes.reverted) { + if (!symbolResultBytes.reverted && !isNullEthValue(symbolResultBytes.value.toHexString())) { // for broken pairs that have no symbol function exposed if (!isNullEthValue(symbolResultBytes.value.toHexString())) { symbolValue = symbolResultBytes.value.toString() - } else { - // try with the static definition - const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) - if (staticTokenDefinition != null) { - symbolValue = staticTokenDefinition.symbol - } } } } else { @@ -37,10 +34,13 @@ export function fetchTokenSymbol( return symbolValue } -export function fetchTokenName( - tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, -): string { +export function fetchTokenName(tokenAddress: Address, tokenOverrides: StaticTokenDefinition[]): string { + // try with the static definition + const staticTokenDefinition = getStaticDefinition(tokenAddress, tokenOverrides) + if (staticTokenDefinition != null) { + return staticTokenDefinition.name + } + const contract = ERC20.bind(tokenAddress) const contractNameBytes = ERC20NameBytes.bind(tokenAddress) @@ -53,12 +53,6 @@ export function fetchTokenName( // for broken exchanges that have no name function exposed if (!isNullEthValue(nameResultBytes.value.toHexString())) { nameValue = nameResultBytes.value.toString() - } else { - // try with the static definition - const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) - if (staticTokenDefinition != null) { - nameValue = staticTokenDefinition.name - } } } } else { @@ -78,10 +72,13 @@ export function fetchTokenTotalSupply(tokenAddress: Address): BigInt { return totalSupplyValue } -export function fetchTokenDecimals( - tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, -): BigInt | null { +export function fetchTokenDecimals(tokenAddress: Address, tokenOverrides: StaticTokenDefinition[]): BigInt | null { + // try with the static definition + const staticTokenDefinition = getStaticDefinition(tokenAddress, tokenOverrides) + if (staticTokenDefinition) { + return staticTokenDefinition.decimals + } + const contract = ERC20.bind(tokenAddress) // try types uint8 for decimals const decimalResult = contract.try_decimals() @@ -90,12 +87,6 @@ export function fetchTokenDecimals( if (decimalResult.value.lt(BigInt.fromI32(255))) { return decimalResult.value } - } else { - // try with the static definition - const staticTokenDefinition = getStaticDefinition(tokenAddress, staticTokenDefinitions) - if (staticTokenDefinition) { - return staticTokenDefinition.decimals - } } return null diff --git a/subgraph.yaml b/subgraph.yaml index 10e7cb55..d4024c55 100644 --- a/subgraph.yaml +++ b/subgraph.yaml @@ -9,11 +9,11 @@ features: dataSources: - kind: ethereum/contract name: Factory - network: mainnet + network: base source: - address: '0x1F98431c8aD98523631AE4a59f267346ea31F984' abi: Factory - startBlock: 12369621 + address: "0x33128a8fC17869897dcE68Ed026d694621f6FDfD" + startBlock: 2009445 mapping: kind: ethereum/events apiVersion: 0.0.7 @@ -39,7 +39,7 @@ dataSources: templates: - kind: ethereum/contract name: Pool - network: mainnet + network: base source: abi: Pool mapping: @@ -62,9 +62,11 @@ templates: handler: handleInitialize - event: Swap(indexed address,indexed address,int256,int256,uint160,uint128,int24) handler: handleSwap - - event: Mint(address,indexed address,indexed int24,indexed int24,uint128,uint256,uint256) + - event: Mint(address,indexed address,indexed int24,indexed + int24,uint128,uint256,uint256) 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) + - event: Collect(indexed address,address,indexed int24,indexed + int24,uint128,uint128) handler: handleCollect diff --git a/tests/constants.ts b/tests/constants.ts index 4993604a..5b6166b1 100644 --- a/tests/constants.ts +++ b/tests/constants.ts @@ -4,15 +4,58 @@ import { assert, createMockedFunction, newMockEvent } from 'matchstick-as' import { handlePoolCreatedHelper } from '../src/mappings/factory' import { PoolCreated } from '../src/types/Factory/Factory' import { Pool, Token } from '../src/types/schema' +import { SubgraphConfig } from '../src/utils/chains' import { ZERO_BD, ZERO_BI } from '../src/utils/constants' +const FACTORY_ADDRESS = '0x1F98431c8aD98523631AE4a59f267346ea31F984' const USDC_MAINNET_ADDRESS = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48' const WETH_MAINNET_ADDRESS = '0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2' const WBTC_MAINNET_ADDRESS = '0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599' export const USDC_WETH_03_MAINNET_POOL = '0x8ad599c3a0ff1de082011efddc58f1908eb6e6d8' export const WBTC_WETH_03_MAINNET_POOL = '0xcbcdf9626bc03e24f779434178a73a0b4bad62ed' export const POOL_FEE_TIER_03 = 3000 -export const POOL_TICK_SPACING_03 = 60 + +export const TEST_CONFIG: SubgraphConfig = { + factoryAddress: FACTORY_ADDRESS, + stablecoinWrappedNativePoolAddress: USDC_WETH_03_MAINNET_POOL, + stablecoinIsToken0: true, + wrappedNativeAddress: WETH_MAINNET_ADDRESS, + minimumNativeLocked: ZERO_BD, + poolsToSkip: [], + stablecoinAddresses: [USDC_MAINNET_ADDRESS], + whitelistTokens: [WETH_MAINNET_ADDRESS, USDC_MAINNET_ADDRESS], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], +} + +export const TEST_CONFIG_WITH_NO_WHITELIST: SubgraphConfig = { + factoryAddress: FACTORY_ADDRESS, + stablecoinWrappedNativePoolAddress: USDC_WETH_03_MAINNET_POOL, + stablecoinIsToken0: true, + wrappedNativeAddress: WETH_MAINNET_ADDRESS, + minimumNativeLocked: ZERO_BD, + poolsToSkip: [], + stablecoinAddresses: [USDC_MAINNET_ADDRESS], + whitelistTokens: [], + tokenOverrides: [], + poolsToSkip: [], + poolMappings: [], +} + +export const TEST_CONFIG_WITH_POOL_SKIPPED: SubgraphConfig = { + factoryAddress: FACTORY_ADDRESS, + stablecoinWrappedNativePoolAddress: USDC_WETH_03_MAINNET_POOL, + stablecoinIsToken0: true, + wrappedNativeAddress: WETH_MAINNET_ADDRESS, + minimumNativeLocked: ZERO_BD, + poolsToSkip: [], + stablecoinAddresses: [USDC_MAINNET_ADDRESS], + whitelistTokens: [WETH_MAINNET_ADDRESS, USDC_MAINNET_ADDRESS], + tokenOverrides: [], + poolsToSkip: [USDC_WETH_03_MAINNET_POOL], + poolMappings: [], +} export class TokenFixture { address: string @@ -20,6 +63,7 @@ export class TokenFixture { name: string totalSupply: string decimals: string + balanceOf: string } export const USDC_MAINNET_FIXTURE: TokenFixture = { @@ -28,6 +72,7 @@ export const USDC_MAINNET_FIXTURE: TokenFixture = { name: 'USD Coin', totalSupply: '300', decimals: '6', + balanceOf: '1000', } export const WETH_MAINNET_FIXTURE: TokenFixture = { @@ -36,6 +81,7 @@ export const WETH_MAINNET_FIXTURE: TokenFixture = { name: 'Wrapped Ether', totalSupply: '100', decimals: '18', + balanceOf: '500', } export const WBTC_MAINNET_FIXTURE: TokenFixture = { @@ -44,6 +90,56 @@ export const WBTC_MAINNET_FIXTURE: TokenFixture = { name: 'Wrapped Bitcoin', totalSupply: '200', decimals: '8', + balanceOf: '750', +} + +export const getTokenFixture = (tokenAddress: string): TokenFixture => { + if (tokenAddress == USDC_MAINNET_FIXTURE.address) { + return USDC_MAINNET_FIXTURE + } else if (tokenAddress == WETH_MAINNET_FIXTURE.address) { + return WETH_MAINNET_FIXTURE + } else if (tokenAddress == WBTC_MAINNET_FIXTURE.address) { + return WBTC_MAINNET_FIXTURE + } else { + throw new Error('Token address not found in fixtures') + } +} + +export class PoolFixture { + address: string + token0: TokenFixture + token1: TokenFixture + feeTier: string + tickSpacing: string + liquidity: string +} + +export const USDC_WETH_03_MAINNET_POOL_FIXTURE: PoolFixture = { + address: USDC_WETH_03_MAINNET_POOL, + token0: USDC_MAINNET_FIXTURE, + token1: WETH_MAINNET_FIXTURE, + feeTier: '3000', + tickSpacing: '60', + liquidity: '100', +} + +export const WBTC_WETH_03_MAINNET_POOL_FIXTURE: PoolFixture = { + address: WBTC_WETH_03_MAINNET_POOL, + token0: WBTC_MAINNET_FIXTURE, + token1: WETH_MAINNET_FIXTURE, + feeTier: '3000', + tickSpacing: '60', + liquidity: '200', +} + +export const getPoolFixture = (poolAddress: string): PoolFixture => { + if (poolAddress == USDC_WETH_03_MAINNET_POOL) { + return USDC_WETH_03_MAINNET_POOL_FIXTURE + } else if (poolAddress == WBTC_WETH_03_MAINNET_POOL) { + return WBTC_WETH_03_MAINNET_POOL_FIXTURE + } else { + throw new Error('Pool address not found in fixtures') + } } export const TEST_ETH_PRICE_USD = BigDecimal.fromString('2000') @@ -54,22 +150,23 @@ export const MOCK_EVENT = newMockEvent() export const invokePoolCreatedWithMockedEthCalls = ( mockEvent: ethereum.Event, - factoryAddress: string, - token0: TokenFixture, - token1: TokenFixture, - poolAddressHexString: string, - feeTier: number, - tickSpacing: number, + subgraphConfig: SubgraphConfig, ): void => { + const pool = getPoolFixture(subgraphConfig.stablecoinWrappedNativePoolAddress) + const feeTier = pool.feeTier + const tickSpacing = pool.tickSpacing + const token0 = getTokenFixture(pool.token0.address) + const token1 = getTokenFixture(pool.token1.address) + const mockEvent = newMockEvent() const token0Address = Address.fromString(token0.address) const token1Address = Address.fromString(token1.address) - const poolAddress = Address.fromString(poolAddressHexString) + const poolAddress = Address.fromString(subgraphConfig.stablecoinWrappedNativePoolAddress) const parameters = [ new ethereum.EventParam('token0', ethereum.Value.fromAddress(token0Address)), new ethereum.EventParam('token1', ethereum.Value.fromAddress(token1Address)), - new ethereum.EventParam('fee', ethereum.Value.fromI32(feeTier as i32)), - new ethereum.EventParam('tickSpacing', ethereum.Value.fromI32(tickSpacing as i32)), + new ethereum.EventParam('fee', ethereum.Value.fromI32(parseInt(feeTier) as i32)), + new ethereum.EventParam('tickSpacing', ethereum.Value.fromI32(parseInt(tickSpacing) as i32)), new ethereum.EventParam('pool', ethereum.Value.fromAddress(poolAddress)), ] const poolCreatedEvent = new PoolCreated( @@ -100,18 +197,18 @@ export const invokePoolCreatedWithMockedEthCalls = ( createMockedFunction(token1Address, 'decimals', 'decimals():(uint32)').returns([ ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token1.decimals)), ]) - handlePoolCreatedHelper(poolCreatedEvent, factoryAddress, [token0.address, token1.address]) + handlePoolCreatedHelper(poolCreatedEvent, subgraphConfig) } // More lightweight than the method above which invokes handlePoolCreated. This // method only creates the pool entity while the above method also creates the // relevant token and factory entities. -export const createAndStoreTestPool = ( - poolAddress: string, - token0Address: string, - token1Address: string, - feeTier: i32, -): Pool => { +export const createAndStoreTestPool = (poolFixture: PoolFixture): Pool => { + const poolAddress = poolFixture.address + const token0Address = poolFixture.token0.address + const token1Address = poolFixture.token1.address + const feeTier = parseInt(poolFixture.feeTier) as i32 + const pool = new Pool(poolAddress) pool.createdAtTimestamp = ZERO_BI pool.createdAtBlockNumber = ZERO_BI diff --git a/tests/handleBurn.test.ts b/tests/handleBurn.test.ts index 618d8c55..b3b1562d 100644 --- a/tests/handleBurn.test.ts +++ b/tests/handleBurn.test.ts @@ -5,13 +5,12 @@ import { handleBurnHelper } from '../src/mappings/pool/burn' import { Bundle, Pool, Tick, Token } from '../src/types/schema' import { Burn } from '../src/types/templates/Pool/Pool' import { convertTokenToDecimal, fastExponentiation, safeDiv } from '../src/utils' -import { FACTORY_ADDRESS, ONE_BD, ZERO_BI } from '../src/utils/constants' +import { ONE_BD, ZERO_BI } from '../src/utils/constants' import { assertObjectMatches, invokePoolCreatedWithMockedEthCalls, MOCK_EVENT, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + TEST_CONFIG, TEST_ETH_PRICE_USD, TEST_USDC_DERIVED_ETH, TEST_WETH_DERIVED_ETH, @@ -59,15 +58,7 @@ const BURN_EVENT = new Burn( describe('handleBurn', () => { beforeAll(() => { - invokePoolCreatedWithMockedEthCalls( - MOCK_EVENT, - FACTORY_ADDRESS, - USDC_MAINNET_FIXTURE, - WETH_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, - ) + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG) const bundle = new Bundle('1') bundle.ethPriceUSD = TEST_ETH_PRICE_USD @@ -113,7 +104,7 @@ describe('handleBurn', () => { pool.tick = BigInt.fromI32(BURN_FIXTURE.tickLower + BURN_FIXTURE.tickUpper).div(BigInt.fromI32(2)) pool.save() - handleBurnHelper(BURN_EVENT, FACTORY_ADDRESS) + handleBurnHelper(BURN_EVENT, TEST_CONFIG) const amountToken0 = convertTokenToDecimal(BURN_FIXTURE.amount0, BigInt.fromString(USDC_MAINNET_FIXTURE.decimals)) const amountToken1 = convertTokenToDecimal(BURN_FIXTURE.amount1, BigInt.fromString(WETH_MAINNET_FIXTURE.decimals)) @@ -122,7 +113,7 @@ describe('handleBurn', () => { .plus(amountToken1.times(TEST_WETH_DERIVED_ETH)) const poolTotalValueLockedUSD = poolTotalValueLockedETH.times(TEST_ETH_PRICE_USD) - assertObjectMatches('Factory', FACTORY_ADDRESS, [ + assertObjectMatches('Factory', TEST_CONFIG.factoryAddress, [ ['txCount', '1'], ['totalValueLockedETH', '0'], ['totalValueLockedUSD', '0'], @@ -186,7 +177,7 @@ describe('handleBurn', () => { const liquidityBeforeBurn = pool.liquidity pool.save() - handleBurnHelper(BURN_EVENT, FACTORY_ADDRESS) + handleBurnHelper(BURN_EVENT, TEST_CONFIG) // liquidity should not be updated assertObjectMatches('Pool', USDC_WETH_03_MAINNET_POOL, [['liquidity', liquidityBeforeBurn.toString()]]) diff --git a/tests/handleCollect.test.ts b/tests/handleCollect.test.ts index 05b48c85..e9542d94 100644 --- a/tests/handleCollect.test.ts +++ b/tests/handleCollect.test.ts @@ -5,13 +5,13 @@ import { handleCollectHelper } from '../src/mappings/pool/collect' import { Bundle, Token } from '../src/types/schema' import { Collect } from '../src/types/templates/Pool/Pool' import { convertTokenToDecimal } from '../src/utils' -import { FACTORY_ADDRESS, ZERO_BD } from '../src/utils/constants' +import { ZERO_BD } from '../src/utils/constants' import { assertObjectMatches, invokePoolCreatedWithMockedEthCalls, MOCK_EVENT, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + TEST_CONFIG, + TEST_CONFIG_WITH_NO_WHITELIST, TEST_ETH_PRICE_USD, TEST_USDC_DERIVED_ETH, TEST_WETH_DERIVED_ETH, @@ -59,15 +59,7 @@ const COLLECT_EVENT = new Collect( describe('handleMint', () => { beforeAll(() => { - invokePoolCreatedWithMockedEthCalls( - MOCK_EVENT, - FACTORY_ADDRESS, - USDC_MAINNET_FIXTURE, - WETH_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, - ) + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG) const bundle = new Bundle('1') bundle.ethPriceUSD = TEST_ETH_PRICE_USD @@ -86,7 +78,7 @@ describe('handleMint', () => { // pass in empty whitelist to simplify this test. Doing so ignores the // effect of getTrackedAmountUSD which we test separately. const trackedCollectedAmountUSD = ZERO_BD - handleCollectHelper(COLLECT_EVENT, FACTORY_ADDRESS, []) + handleCollectHelper(COLLECT_EVENT, TEST_CONFIG_WITH_NO_WHITELIST) const collectedAmountToken0 = convertTokenToDecimal( COLLECT_FIXTURE.amount0, @@ -101,7 +93,7 @@ describe('handleMint', () => { .plus(collectedAmountToken1.times(TEST_WETH_DERIVED_ETH)) const collectedAmountUSD = collectedAmountETH.times(TEST_ETH_PRICE_USD) - assertObjectMatches('Factory', FACTORY_ADDRESS, [ + assertObjectMatches('Factory', TEST_CONFIG.factoryAddress, [ ['txCount', '1'], ['totalValueLockedETH', collectedAmountETH.neg().toString()], ['totalValueLockedUSD', collectedAmountUSD.neg().toString()], diff --git a/tests/handleInitialize.test.ts b/tests/handleInitialize.test.ts index f9a569b5..e560cb98 100644 --- a/tests/handleInitialize.test.ts +++ b/tests/handleInitialize.test.ts @@ -5,19 +5,21 @@ import { handleInitializeHelper } from '../src/mappings/pool/initialize' import { Bundle, Pool, Token } from '../src/types/schema' import { Initialize } from '../src/types/templates/Pool/Pool' import { safeDiv } from '../src/utils' -import { ADDRESS_ZERO, ZERO_BD } from '../src/utils/constants' -import { findEthPerToken, getEthPriceInUSD } from '../src/utils/pricing' +import { ADDRESS_ZERO } from '../src/utils/constants' +import { findNativePerToken, getNativePriceInUSD } from '../src/utils/pricing' import { assertObjectMatches, createAndStoreTestPool, createAndStoreTestToken, MOCK_EVENT, - POOL_FEE_TIER_03, + TEST_CONFIG, TEST_ETH_PRICE_USD, USDC_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, + USDC_WETH_03_MAINNET_POOL_FIXTURE, WBTC_MAINNET_FIXTURE, WBTC_WETH_03_MAINNET_POOL, + WBTC_WETH_03_MAINNET_POOL_FIXTURE, WETH_MAINNET_FIXTURE, } from './constants' @@ -47,12 +49,7 @@ const INITIALIZE_EVENT = new Initialize( describe('handleInitialize', () => { test('success', () => { - createAndStoreTestPool( - USDC_WETH_03_MAINNET_POOL, - USDC_MAINNET_FIXTURE.address, - WETH_MAINNET_FIXTURE.address, - POOL_FEE_TIER_03, - ) + createAndStoreTestPool(USDC_WETH_03_MAINNET_POOL_FIXTURE) const token0 = createAndStoreTestToken(USDC_MAINNET_FIXTURE) const token1 = createAndStoreTestToken(WETH_MAINNET_FIXTURE) @@ -61,42 +58,29 @@ describe('handleInitialize', () => { bundle.ethPriceUSD = TEST_ETH_PRICE_USD bundle.save() - const stablecoinWrappedNativePoolAddress = USDC_WETH_03_MAINNET_POOL - const stablecoinIsToken0 = true - const wrappedNativeAddress = WETH_MAINNET_FIXTURE.address - const stablecoinAddresses = [USDC_MAINNET_FIXTURE.address] - const minimumEthLocked = ZERO_BD - - handleInitializeHelper( - INITIALIZE_EVENT, - stablecoinWrappedNativePoolAddress, - stablecoinIsToken0, - wrappedNativeAddress, - stablecoinAddresses, - minimumEthLocked, - ) + handleInitializeHelper(INITIALIZE_EVENT, TEST_CONFIG) assertObjectMatches('Pool', USDC_WETH_03_MAINNET_POOL, [ ['sqrtPrice', INITIALIZE_FIXTURE.sqrtPriceX96.toString()], ['tick', INITIALIZE_FIXTURE.tick.toString()], ]) - const expectedEthPrice = getEthPriceInUSD(USDC_WETH_03_MAINNET_POOL, true) + const expectedEthPrice = getNativePriceInUSD(USDC_WETH_03_MAINNET_POOL, true) assertObjectMatches('Bundle', '1', [['ethPriceUSD', expectedEthPrice.toString()]]) - const expectedToken0Price = findEthPerToken( + const expectedToken0Price = findNativePerToken( token0 as Token, - wrappedNativeAddress, - stablecoinAddresses, - minimumEthLocked, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, ) assertObjectMatches('Token', USDC_MAINNET_FIXTURE.address, [['derivedETH', expectedToken0Price.toString()]]) - const expectedToken1Price = findEthPerToken( + const expectedToken1Price = findNativePerToken( token1 as Token, - wrappedNativeAddress, - stablecoinAddresses, - minimumEthLocked, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, ) assertObjectMatches('Token', WETH_MAINNET_FIXTURE.address, [['derivedETH', expectedToken1Price.toString()]]) }) @@ -105,12 +89,7 @@ describe('handleInitialize', () => { describe('getEthPriceInUSD', () => { beforeEach(() => { clearStore() - createAndStoreTestPool( - USDC_WETH_03_MAINNET_POOL, - USDC_MAINNET_FIXTURE.address, - WETH_MAINNET_FIXTURE.address, - POOL_FEE_TIER_03, - ) + createAndStoreTestPool(USDC_WETH_03_MAINNET_POOL_FIXTURE) }) test('success - stablecoin is token0', () => { @@ -118,7 +97,7 @@ describe('getEthPriceInUSD', () => { pool.token0Price = BigDecimal.fromString('1') pool.save() - const ethPriceUSD = getEthPriceInUSD(USDC_WETH_03_MAINNET_POOL, true) + const ethPriceUSD = getNativePriceInUSD(USDC_WETH_03_MAINNET_POOL, true) assert.assertTrue(ethPriceUSD == BigDecimal.fromString('1')) }) @@ -128,7 +107,7 @@ describe('getEthPriceInUSD', () => { pool.token1Price = BigDecimal.fromString('1') pool.save() - const ethPriceUSD = getEthPriceInUSD(USDC_WETH_03_MAINNET_POOL, false) + const ethPriceUSD = getNativePriceInUSD(USDC_WETH_03_MAINNET_POOL, false) assert.assertTrue(ethPriceUSD == BigDecimal.fromString('1')) }) @@ -139,12 +118,12 @@ describe('getEthPriceInUSD', () => { pool.token1Price = BigDecimal.fromString('1') pool.save() - const ethPriceUSD = getEthPriceInUSD(ADDRESS_ZERO) + const ethPriceUSD = getNativePriceInUSD(ADDRESS_ZERO, true) assert.assertTrue(ethPriceUSD == BigDecimal.fromString('0')) }) }) -describe('findEthPerToken', () => { +describe('findNativePerToken', () => { beforeEach(() => { clearStore() @@ -155,24 +134,29 @@ describe('findEthPerToken', () => { test('success - token is wrapped native', () => { const token = createAndStoreTestToken(WETH_MAINNET_FIXTURE) - const ethPerToken = findEthPerToken(token as Token, WETH_MAINNET_FIXTURE.address) + const ethPerToken = findNativePerToken( + token as Token, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) assert.assertTrue(ethPerToken == BigDecimal.fromString('1')) }) test('success - token is stablecoin', () => { const token = createAndStoreTestToken(USDC_MAINNET_FIXTURE) - const ethPerToken = findEthPerToken(token as Token, WETH_MAINNET_FIXTURE.address, [USDC_MAINNET_FIXTURE.address]) + const ethPerToken = findNativePerToken( + token as Token, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) const expectedStablecoinPrice = safeDiv(BigDecimal.fromString('1'), TEST_ETH_PRICE_USD) assert.assertTrue(ethPerToken == expectedStablecoinPrice) }) test('success - token is not wrapped native or stablecoin', () => { - const pool = createAndStoreTestPool( - WBTC_WETH_03_MAINNET_POOL, - WBTC_MAINNET_FIXTURE.address, - WETH_MAINNET_FIXTURE.address, - POOL_FEE_TIER_03, - ) + const pool = createAndStoreTestPool(WBTC_WETH_03_MAINNET_POOL_FIXTURE) const minimumEthLocked = BigDecimal.fromString('0') @@ -189,7 +173,7 @@ describe('findEthPerToken', () => { token1.derivedETH = BigDecimal.fromString('10') token1.save() - const ethPerToken = findEthPerToken( + const ethPerToken = findNativePerToken( token0 as Token, WETH_MAINNET_FIXTURE.address, [USDC_MAINNET_FIXTURE.address], @@ -201,7 +185,12 @@ describe('findEthPerToken', () => { test('success - token is not wrapped native or stablecoin, but has no pools', () => { const token0 = createAndStoreTestToken(WBTC_MAINNET_FIXTURE) - const ethPerToken = findEthPerToken(token0 as Token) + const ethPerToken = findNativePerToken( + token0 as Token, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) assert.assertTrue(ethPerToken == BigDecimal.fromString('0')) }) @@ -210,7 +199,12 @@ describe('findEthPerToken', () => { token0.whitelistPools = [WBTC_WETH_03_MAINNET_POOL] token0.save() - const ethPerToken = findEthPerToken(token0 as Token) + const ethPerToken = findNativePerToken( + token0 as Token, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) assert.assertTrue(ethPerToken == BigDecimal.fromString('0')) }) }) diff --git a/tests/handleMint.test.ts b/tests/handleMint.test.ts index 4248787c..c6705caa 100644 --- a/tests/handleMint.test.ts +++ b/tests/handleMint.test.ts @@ -5,13 +5,12 @@ import { handleMintHelper } from '../src/mappings/pool/mint' import { Bundle, Pool, Token } from '../src/types/schema' import { Mint } from '../src/types/templates/Pool/Pool' import { convertTokenToDecimal, fastExponentiation, safeDiv } from '../src/utils' -import { FACTORY_ADDRESS, ONE_BD } from '../src/utils/constants' +import { ONE_BD } from '../src/utils/constants' import { assertObjectMatches, invokePoolCreatedWithMockedEthCalls, MOCK_EVENT, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + TEST_CONFIG, TEST_ETH_PRICE_USD, TEST_USDC_DERIVED_ETH, TEST_WETH_DERIVED_ETH, @@ -62,15 +61,7 @@ const MINT_EVENT = new Mint( describe('handleMint', () => { beforeAll(() => { - invokePoolCreatedWithMockedEthCalls( - MOCK_EVENT, - FACTORY_ADDRESS, - USDC_MAINNET_FIXTURE, - WETH_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, - ) + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG) const bundle = new Bundle('1') bundle.ethPriceUSD = TEST_ETH_PRICE_USD @@ -91,7 +82,7 @@ describe('handleMint', () => { pool.tick = BigInt.fromI32(MINT_FIXTURE.tickLower + MINT_FIXTURE.tickUpper).div(BigInt.fromI32(2)) pool.save() - handleMintHelper(MINT_EVENT, FACTORY_ADDRESS) + handleMintHelper(MINT_EVENT, TEST_CONFIG) const amountToken0 = convertTokenToDecimal(MINT_FIXTURE.amount0, BigInt.fromString(USDC_MAINNET_FIXTURE.decimals)) const amountToken1 = convertTokenToDecimal(MINT_FIXTURE.amount1, BigInt.fromString(WETH_MAINNET_FIXTURE.decimals)) @@ -100,7 +91,7 @@ describe('handleMint', () => { .plus(amountToken1.times(TEST_WETH_DERIVED_ETH)) const poolTotalValueLockedUSD = poolTotalValueLockedETH.times(TEST_ETH_PRICE_USD) - assertObjectMatches('Factory', FACTORY_ADDRESS, [ + assertObjectMatches('Factory', TEST_CONFIG.factoryAddress, [ ['txCount', '1'], ['totalValueLockedETH', poolTotalValueLockedETH.toString()], ['totalValueLockedUSD', poolTotalValueLockedUSD.toString()], @@ -179,7 +170,7 @@ describe('handleMint', () => { const liquidityBeforeMint = pool.liquidity pool.save() - handleMintHelper(MINT_EVENT, FACTORY_ADDRESS) + handleMintHelper(MINT_EVENT, TEST_CONFIG) // liquidity should not be updated assertObjectMatches('Pool', USDC_WETH_03_MAINNET_POOL, [['liquidity', liquidityBeforeMint.toString()]]) diff --git a/tests/handlePoolCreated.test.ts b/tests/handlePoolCreated.test.ts index 74fad2d4..55845640 100644 --- a/tests/handlePoolCreated.test.ts +++ b/tests/handlePoolCreated.test.ts @@ -1,40 +1,43 @@ import { Address, BigInt, Bytes, ethereum } from '@graphprotocol/graph-ts' -import { assert, createMockedFunction, test } from 'matchstick-as/assembly/index' +import { assert, beforeEach, clearStore, createMockedFunction, test } from 'matchstick-as/assembly/index' import { describe, test } from 'matchstick-as/assembly/index' -import { NULL_ETH_HEX_STRING } from '../src/utils' -import { FACTORY_ADDRESS } from '../src/utils/constants' +import { populateEmptyPools } from '../src/backfill' +import { convertTokenToDecimal, NULL_ETH_HEX_STRING } from '../src/utils' import { StaticTokenDefinition } from '../src/utils/staticTokenDefinition' import { fetchTokenDecimals, fetchTokenName, fetchTokenSymbol, fetchTokenTotalSupply } from '../src/utils/token' import { assertObjectMatches, + getPoolFixture, + getTokenFixture, invokePoolCreatedWithMockedEthCalls, MOCK_EVENT, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + TEST_CONFIG, + TEST_CONFIG_WITH_POOL_SKIPPED, USDC_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - WETH_MAINNET_FIXTURE, + USDC_WETH_03_MAINNET_POOL_FIXTURE, } from './constants' describe('handlePoolCreated', () => { + beforeEach(() => { + clearStore() + }) + test('success - create a pool', () => { - assert.notInStore('Factory', FACTORY_ADDRESS) - assert.notInStore('Pool', USDC_WETH_03_MAINNET_POOL) - assert.notInStore('Token', USDC_MAINNET_FIXTURE.address) - assert.notInStore('Token', USDC_MAINNET_FIXTURE.address) - - invokePoolCreatedWithMockedEthCalls( - MOCK_EVENT, - FACTORY_ADDRESS, - USDC_MAINNET_FIXTURE, - WETH_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, - ) - - assertObjectMatches('Factory', FACTORY_ADDRESS, [ + const poolAddress = TEST_CONFIG.stablecoinWrappedNativePoolAddress + const poolFixture = getPoolFixture(poolAddress) + const token0Fixture = getTokenFixture(poolFixture.token0.address) + const token1Fixture = getTokenFixture(poolFixture.token1.address) + + assert.notInStore('Factory', TEST_CONFIG.factoryAddress) + assert.notInStore('Pool', poolAddress) + + assert.notInStore('Token', token0Fixture.address) + assert.notInStore('Token', token1Fixture.address) + + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG) + + assertObjectMatches('Factory', TEST_CONFIG.factoryAddress, [ ['poolCount', '1'], ['totalVolumeETH', '0'], ['totalVolumeUSD', '0'], @@ -49,11 +52,11 @@ describe('handlePoolCreated', () => { assertObjectMatches('Bundle', '1', [['ethPriceUSD', '0']]) - assertObjectMatches('Token', USDC_MAINNET_FIXTURE.address, [ - ['symbol', USDC_MAINNET_FIXTURE.symbol], - ['name', USDC_MAINNET_FIXTURE.name], - ['totalSupply', USDC_MAINNET_FIXTURE.totalSupply], - ['decimals', USDC_MAINNET_FIXTURE.decimals], + assertObjectMatches('Token', token0Fixture.address, [ + ['symbol', token0Fixture.symbol], + ['name', token0Fixture.name], + ['totalSupply', token0Fixture.totalSupply], + ['decimals', token0Fixture.decimals], ['derivedETH', '0'], ['volume', '0'], ['volumeUSD', '0'], @@ -64,14 +67,14 @@ describe('handlePoolCreated', () => { ['totalValueLockedUSDUntracked', '0'], ['txCount', '0'], ['poolCount', '0'], - ['whitelistPools', `[${USDC_WETH_03_MAINNET_POOL}]`], + ['whitelistPools', `[${poolAddress}]`], ]) - assertObjectMatches('Token', WETH_MAINNET_FIXTURE.address, [ - ['symbol', WETH_MAINNET_FIXTURE.symbol], - ['name', WETH_MAINNET_FIXTURE.name], - ['totalSupply', WETH_MAINNET_FIXTURE.totalSupply], - ['decimals', WETH_MAINNET_FIXTURE.decimals], + assertObjectMatches('Token', token1Fixture.address, [ + ['symbol', token1Fixture.symbol], + ['name', token1Fixture.name], + ['totalSupply', token1Fixture.totalSupply], + ['decimals', token1Fixture.decimals], ['derivedETH', '0'], ['volume', '0'], ['volumeUSD', '0'], @@ -82,13 +85,13 @@ describe('handlePoolCreated', () => { ['totalValueLockedUSDUntracked', '0'], ['txCount', '0'], ['poolCount', '0'], - ['whitelistPools', `[${USDC_WETH_03_MAINNET_POOL}]`], + ['whitelistPools', `[${poolAddress}]`], ]) - assertObjectMatches('Pool', USDC_WETH_03_MAINNET_POOL, [ - ['token0', USDC_MAINNET_FIXTURE.address], - ['token1', WETH_MAINNET_FIXTURE.address], - ['feeTier', POOL_FEE_TIER_03.toString()], + assertObjectMatches('Pool', poolAddress, [ + ['token0', token0Fixture.address], + ['token1', token1Fixture.address], + ['feeTier', poolFixture.feeTier.toString()], ['createdAtTimestamp', MOCK_EVENT.block.timestamp.toString()], ['createdAtBlockNumber', MOCK_EVENT.block.number.toString()], ['liquidityProviderCount', '0'], @@ -113,11 +116,159 @@ describe('handlePoolCreated', () => { ]) }) + test('success - skip pool creation if address in poolToSkip', () => { + const poolAddress = TEST_CONFIG_WITH_POOL_SKIPPED.stablecoinWrappedNativePoolAddress + const poolFixture = getPoolFixture(poolAddress) + const token0Fixture = getTokenFixture(poolFixture.token0.address) + const token1Fixture = getTokenFixture(poolFixture.token1.address) + + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG_WITH_POOL_SKIPPED) + + assert.notInStore('Factory', TEST_CONFIG.factoryAddress) + assert.notInStore('Pool', poolAddress) + + assert.notInStore('Token', token0Fixture.address) + assert.notInStore('Token', token1Fixture.address) + }) + + describe('populateEmptyPools', () => { + test('success', () => { + const poolAddress = Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.address) + createMockedFunction(poolAddress, 'liquidity', 'liquidity():(uint128)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.liquidity)), + ]) + createMockedFunction(poolAddress, 'fee', 'fee():(uint24)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.feeTier)), + ]) + + const token0Fixture = USDC_WETH_03_MAINNET_POOL_FIXTURE.token0 + const token0Address = Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.token0.address) + createMockedFunction(token0Address, 'symbol', 'symbol():(string)').returns([ + ethereum.Value.fromString(token0Fixture.symbol), + ]) + createMockedFunction(token0Address, 'name', 'name():(string)').returns([ + ethereum.Value.fromString(token0Fixture.name), + ]) + createMockedFunction(token0Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token0Fixture.totalSupply)), + ]) + createMockedFunction(token0Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token0Fixture.decimals)), + ]) + createMockedFunction(token0Address, 'balanceOf', 'balanceOf(address):(uint256)') + .withArgs([ethereum.Value.fromAddress(Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.address))]) + .returns([ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token0Fixture.balanceOf))]) + + const token1Fixture = USDC_WETH_03_MAINNET_POOL_FIXTURE.token1 + const token1Address = Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.token1.address) + createMockedFunction(token1Address, 'symbol', 'symbol():(string)').returns([ + ethereum.Value.fromString(token1Fixture.symbol), + ]) + createMockedFunction(token1Address, 'name', 'name():(string)').returns([ + ethereum.Value.fromString(token1Fixture.name), + ]) + createMockedFunction(token1Address, 'totalSupply', 'totalSupply():(uint256)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token1Fixture.totalSupply)), + ]) + createMockedFunction(token1Address, 'decimals', 'decimals():(uint32)').returns([ + ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token1Fixture.decimals)), + ]) + createMockedFunction(token1Address, 'balanceOf', 'balanceOf(address):(uint256)') + .withArgs([ethereum.Value.fromAddress(Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.address))]) + .returns([ethereum.Value.fromUnsignedBigInt(BigInt.fromString(token1Fixture.balanceOf))]) + + populateEmptyPools( + MOCK_EVENT, + [ + [ + Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.address), // first address is unused, hence reusing this pool address + Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.address), + Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.token0.address), + Address.fromString(USDC_WETH_03_MAINNET_POOL_FIXTURE.token1.address), + ], + ], + [], + [], + ) + + const tvlToken0 = convertTokenToDecimal( + BigInt.fromString(token0Fixture.balanceOf), + BigInt.fromString(token0Fixture.decimals), + ) + assertObjectMatches('Token', token0Fixture.address, [ + ['symbol', token0Fixture.symbol], + ['name', token0Fixture.name], + ['totalSupply', token0Fixture.totalSupply], + ['decimals', token0Fixture.decimals], + ['derivedETH', '0'], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['totalValueLocked', tvlToken0.toString()], + ['totalValueLockedUSD', '0'], + ['totalValueLockedUSDUntracked', '0'], + ['txCount', '0'], + ['poolCount', '0'], + ['whitelistPools', `[]`], + ]) + + const tvlToken1 = convertTokenToDecimal( + BigInt.fromString(token1Fixture.balanceOf), + BigInt.fromString(token1Fixture.decimals), + ) + assertObjectMatches('Token', token1Fixture.address, [ + ['symbol', token1Fixture.symbol], + ['name', token1Fixture.name], + ['totalSupply', token1Fixture.totalSupply], + ['decimals', token1Fixture.decimals], + ['derivedETH', '0'], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['totalValueLocked', tvlToken1.toString()], + ['totalValueLockedUSD', '0'], + ['totalValueLockedUSDUntracked', '0'], + ['txCount', '0'], + ['poolCount', '0'], + ['whitelistPools', `[]`], + ]) + + assertObjectMatches('Pool', USDC_WETH_03_MAINNET_POOL_FIXTURE.address, [ + ['token0', token0Fixture.address], + ['token1', token1Fixture.address], + ['feeTier', USDC_WETH_03_MAINNET_POOL_FIXTURE.feeTier], + ['createdAtTimestamp', MOCK_EVENT.block.timestamp.toString()], + ['createdAtBlockNumber', MOCK_EVENT.block.number.toString()], + ['liquidityProviderCount', '0'], + ['txCount', '0'], + ['sqrtPrice', '0'], + ['token0Price', '0'], + ['token1Price', '0'], + ['observationIndex', '0'], + ['totalValueLockedToken0', tvlToken0.toString()], + ['totalValueLockedToken1', tvlToken1.toString()], + ['totalValueLockedUSD', '0'], + ['totalValueLockedETH', '0'], + ['totalValueLockedUSDUntracked', '0'], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['collectedFeesToken0', '0'], + ['collectedFeesToken1', '0'], + ['collectedFeesUSD', '0'], + ]) + }) + }) + describe('fetchTokenSymbol', () => { test('success - fetch token symbol', () => { const usdcAddress = Address.fromString(USDC_MAINNET_FIXTURE.address) createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').returns([ethereum.Value.fromString('USDC')]) - const symbol = fetchTokenSymbol(usdcAddress) + const symbol = fetchTokenSymbol(usdcAddress, []) assert.stringEquals(symbol, 'USDC') }) @@ -127,7 +278,7 @@ describe('handlePoolCreated', () => { createMockedFunction(usdcAddress, 'symbol', 'symbol():(bytes32)').returns([ ethereum.Value.fromBytes(Bytes.fromUTF8('USDC')), ]) - const symbol = fetchTokenSymbol(usdcAddress) + const symbol = fetchTokenSymbol(usdcAddress, []) assert.stringEquals(symbol, 'USDC') }) @@ -153,7 +304,7 @@ describe('handlePoolCreated', () => { const usdcAddress = Address.fromString(USDC_MAINNET_FIXTURE.address) createMockedFunction(usdcAddress, 'symbol', 'symbol():(string)').reverts() createMockedFunction(usdcAddress, 'symbol', 'symbol():(bytes32)').reverts() - const symbol = fetchTokenSymbol(usdcAddress) + const symbol = fetchTokenSymbol(usdcAddress, []) assert.stringEquals(symbol, 'unknown') }) }) @@ -162,7 +313,7 @@ describe('handlePoolCreated', () => { test('success - fetch token name', () => { const usdcAddress = Address.fromString(USDC_MAINNET_FIXTURE.address) createMockedFunction(usdcAddress, 'name', 'name():(string)').returns([ethereum.Value.fromString('USD Coin')]) - const name = fetchTokenName(usdcAddress) + const name = fetchTokenName(usdcAddress, []) assert.stringEquals(name, 'USD Coin') }) @@ -172,7 +323,7 @@ describe('handlePoolCreated', () => { createMockedFunction(usdcAddress, 'name', 'name():(bytes32)').returns([ ethereum.Value.fromBytes(Bytes.fromUTF8('USD Coin')), ]) - const name = fetchTokenName(usdcAddress) + const name = fetchTokenName(usdcAddress, []) assert.stringEquals(name, 'USD Coin') }) @@ -198,7 +349,7 @@ describe('handlePoolCreated', () => { const usdcAddress = Address.fromString(USDC_MAINNET_FIXTURE.address) createMockedFunction(usdcAddress, 'name', 'name():(string)').reverts() createMockedFunction(usdcAddress, 'name', 'name():(bytes32)').reverts() - const name = fetchTokenName(usdcAddress) + const name = fetchTokenName(usdcAddress, []) assert.stringEquals(name, 'unknown') }) }) @@ -227,7 +378,7 @@ describe('handlePoolCreated', () => { createMockedFunction(usdcAddress, 'decimals', 'decimals():(uint32)').returns([ ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(6)), ]) - const decimals = fetchTokenDecimals(usdcAddress) + const decimals = fetchTokenDecimals(usdcAddress, []) assert.assertTrue(decimals == BigInt.fromI32(6)) }) @@ -249,7 +400,7 @@ describe('handlePoolCreated', () => { test('failure - fetch token decimals reverts', () => { const usdcAddress = Address.fromString(USDC_MAINNET_FIXTURE.address) createMockedFunction(usdcAddress, 'decimals', 'decimals():(uint32)').reverts() - const decimals: BigInt | null = fetchTokenDecimals(usdcAddress) + const decimals: BigInt | null = fetchTokenDecimals(usdcAddress, []) assert.assertTrue(decimals === null) }) }) diff --git a/tests/handleSwap.test.ts b/tests/handleSwap.test.ts index 4f6c47de..47c0376c 100644 --- a/tests/handleSwap.test.ts +++ b/tests/handleSwap.test.ts @@ -5,14 +5,19 @@ import { handleSwapHelper } from '../src/mappings/pool/swap' import { Bundle, Token } from '../src/types/schema' import { Swap } from '../src/types/templates/Pool/Pool' import { convertTokenToDecimal, safeDiv } from '../src/utils' -import { FACTORY_ADDRESS, ZERO_BD } from '../src/utils/constants' -import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices } from '../src/utils/pricing' +import { ZERO_BD } from '../src/utils/constants' +import { + findNativePerToken, + getNativePriceInUSD, + getTrackedAmountUSD, + sqrtPriceX96ToTokenPrices, +} from '../src/utils/pricing' import { assertObjectMatches, invokePoolCreatedWithMockedEthCalls, MOCK_EVENT, POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + TEST_CONFIG, TEST_ETH_PRICE_USD, TEST_USDC_DERIVED_ETH, TEST_WETH_DERIVED_ETH, @@ -63,15 +68,7 @@ const SWAP_EVENT = new Swap( describe('handleSwap', () => { beforeAll(() => { - invokePoolCreatedWithMockedEthCalls( - MOCK_EVENT, - FACTORY_ADDRESS, - USDC_MAINNET_FIXTURE, - WETH_MAINNET_FIXTURE, - USDC_WETH_03_MAINNET_POOL, - POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, - ) + invokePoolCreatedWithMockedEthCalls(MOCK_EVENT, TEST_CONFIG) const bundle = new Bundle('1') bundle.ethPriceUSD = TEST_ETH_PRICE_USD @@ -87,13 +84,6 @@ describe('handleSwap', () => { }) test('success', () => { - const stablecoinWrappedNativePoolAddress = USDC_WETH_03_MAINNET_POOL - const stablecoinIsToken0 = true - const wrappedNativeAddress = WETH_MAINNET_FIXTURE.address - const stablecoinAddresses = [USDC_MAINNET_FIXTURE.address] - const minimumEthLocked = ZERO_BD - const whitelistTokens = [USDC_MAINNET_FIXTURE.address, WETH_MAINNET_FIXTURE.address] - const token0 = Token.load(USDC_MAINNET_FIXTURE.address)! const token1 = Token.load(WETH_MAINNET_FIXTURE.address)! @@ -104,9 +94,13 @@ describe('handleSwap', () => { const amount1Abs = amount1.lt(ZERO_BD) ? amount1.times(BigDecimal.fromString('-1')) : amount1 // calculate this before calling handleSwapHelper because it updates the derivedETH of the tokens which will affect calculations - const amountTotalUSDTracked = getTrackedAmountUSD(amount0Abs, token0, amount1Abs, token1, whitelistTokens).div( - BigDecimal.fromString('2'), - ) + const amountTotalUSDTracked = getTrackedAmountUSD( + amount0Abs, + token0, + amount1Abs, + token1, + TEST_CONFIG.whitelistTokens, + ).div(BigDecimal.fromString('2')) const amount0ETH = amount0Abs.times(TEST_USDC_DERIVED_ETH) const amount1ETH = amount1Abs.times(TEST_WETH_DERIVED_ETH) @@ -121,24 +115,26 @@ describe('handleSwap', () => { const feesETH = amountTotalETHTRacked.times(feeTierBD).div(BigDecimal.fromString('1000000')) const feesUSD = amountTotalUSDTracked.times(feeTierBD).div(BigDecimal.fromString('1000000')) - handleSwapHelper( - SWAP_EVENT, - stablecoinWrappedNativePoolAddress, - stablecoinIsToken0, - wrappedNativeAddress, - stablecoinAddresses, - minimumEthLocked, - whitelistTokens, - ) + handleSwapHelper(SWAP_EVENT, TEST_CONFIG) - const newEthPrice = getEthPriceInUSD(USDC_WETH_03_MAINNET_POOL, true) + const newEthPrice = getNativePriceInUSD(USDC_WETH_03_MAINNET_POOL, true) const newPoolPrices = sqrtPriceX96ToTokenPrices(SWAP_FIXTURE.sqrtPriceX96, token0, token1) - const newToken0DerivedETH = findEthPerToken(token0, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) - const newToken1DerivedETH = findEthPerToken(token1, wrappedNativeAddress, stablecoinAddresses, minimumEthLocked) + const newToken0DerivedETH = findNativePerToken( + token0, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) + const newToken1DerivedETH = findNativePerToken( + token1, + TEST_CONFIG.wrappedNativeAddress, + TEST_CONFIG.stablecoinAddresses, + TEST_CONFIG.minimumNativeLocked, + ) const totalValueLockedETH = amount0.times(newToken0DerivedETH).plus(amount1.times(newToken1DerivedETH)) - assertObjectMatches('Factory', FACTORY_ADDRESS, [ + assertObjectMatches('Factory', TEST_CONFIG.factoryAddress, [ ['txCount', '1'], ['totalVolumeETH', amountTotalETHTRacked.toString()], ['totalVolumeUSD', amountTotalUSDTracked.toString()], diff --git a/tests/intervalUpdates.test.ts b/tests/intervalUpdates.test.ts index 120c4e1d..bbc111d8 100644 --- a/tests/intervalUpdates.test.ts +++ b/tests/intervalUpdates.test.ts @@ -2,7 +2,7 @@ import { Address, BigDecimal, BigInt } from '@graphprotocol/graph-ts' import { beforeEach, clearStore, describe, test } from 'matchstick-as' import { Bundle, Factory, Pool, Token } from '../src/types/schema' -import { ADDRESS_ZERO, FACTORY_ADDRESS, ZERO_BD, ZERO_BI } from '../src/utils/constants' +import { ADDRESS_ZERO, ZERO_BD, ZERO_BI } from '../src/utils/constants' import { updatePoolDayData, updatePoolHourData, @@ -16,10 +16,10 @@ import { createAndStoreTestToken, MOCK_EVENT, MOCK_EVENT as poolEvent, - POOL_FEE_TIER_03, + TEST_CONFIG, TEST_ETH_PRICE_USD, - USDC_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, + USDC_WETH_03_MAINNET_POOL_FIXTURE, WETH_MAINNET_FIXTURE, } from './constants' @@ -27,7 +27,7 @@ describe('uniswap interval data', () => { beforeEach(() => { clearStore() - const factory = new Factory(FACTORY_ADDRESS) + const factory = new Factory(TEST_CONFIG.factoryAddress) factory.poolCount = ZERO_BI factory.totalVolumeUSD = ZERO_BD factory.totalVolumeETH = ZERO_BD @@ -46,14 +46,14 @@ describe('uniswap interval data', () => { test('success - create and update uniswapDayData', () => { // these are the only two fields that get persisted to uniswapDayData, set them to non-zero values - const factory = Factory.load(FACTORY_ADDRESS)! + const factory = Factory.load(TEST_CONFIG.factoryAddress)! const uniswapTxCount = BigInt.fromString('10') const uniswapTotalValueLockedUSD = BigDecimal.fromString('100') factory.txCount = uniswapTxCount factory.totalValueLockedUSD = uniswapTotalValueLockedUSD factory.save() - updateUniswapDayData(poolEvent) + updateUniswapDayData(poolEvent, TEST_CONFIG.factoryAddress) const dayId = poolEvent.block.timestamp.toI32() / 86400 const dayStartTimestamp = dayId * 86400 @@ -71,7 +71,7 @@ describe('uniswap interval data', () => { factory.txCount = updatedTxCount factory.save() - updateUniswapDayData(poolEvent) + updateUniswapDayData(poolEvent, TEST_CONFIG.factoryAddress) assertObjectMatches('UniswapDayData', dayId.toString(), [['txCount', updatedTxCount.toString()]]) }) @@ -80,12 +80,7 @@ describe('uniswap interval data', () => { describe('pool interval data', () => { beforeEach(() => { clearStore() - createAndStoreTestPool( - USDC_WETH_03_MAINNET_POOL, - USDC_MAINNET_FIXTURE.address, - WETH_MAINNET_FIXTURE.address, - POOL_FEE_TIER_03, - ) + createAndStoreTestPool(USDC_WETH_03_MAINNET_POOL_FIXTURE) }) test('success - create and update poolDayData', () => {