From 7a4c2b16b81ad1048b0d93b44b54feee51fa341a Mon Sep 17 00:00:00 2001 From: Michael Wang <44713145+mzywang@users.noreply.github.com> Date: Tue, 21 May 2024 11:52:01 -0400 Subject: [PATCH] add unit tests for intervalUpdates --- src/mappings/pool/collect.ts | 2 +- src/utils/intervalUpdates.ts | 5 +- src/utils/pricing.ts | 9 +- src/utils/staticTokenDefinition.ts | 2 +- src/utils/token.ts | 6 +- tests/handleBurn.test.ts | 4 +- tests/handleCollect.test.ts | 8 +- tests/handleMint.test.ts | 4 +- tests/handlePoolCreated.test.ts | 2 +- tests/intervalUpdates.test.ts | 487 +++++++++++++++++++++++++++++ 10 files changed, 507 insertions(+), 22 deletions(-) create mode 100644 tests/intervalUpdates.test.ts diff --git a/src/mappings/pool/collect.ts b/src/mappings/pool/collect.ts index 8bc0be23..9c4d42ad 100644 --- a/src/mappings/pool/collect.ts +++ b/src/mappings/pool/collect.ts @@ -9,7 +9,7 @@ import { updatePoolHourData, updateTokenDayData, updateTokenHourData, - updateUniswapDayData + updateUniswapDayData, } from '../../utils/intervalUpdates' import { getTrackedAmountUSD, WHITELIST_TOKENS } from '../../utils/pricing' diff --git a/src/utils/intervalUpdates.ts b/src/utils/intervalUpdates.ts index fcdfadeb..2d2232b0 100644 --- a/src/utils/intervalUpdates.ts +++ b/src/utils/intervalUpdates.ts @@ -18,8 +18,8 @@ import { FACTORY_ADDRESS } from './constants' * Tracks global aggregate data over daily windows * @param event */ -export function updateUniswapDayData(event: ethereum.Event): UniswapDayData { - const uniswap = Factory.load(FACTORY_ADDRESS)! +export function updateUniswapDayData(event: ethereum.Event, factoryAddress: string = FACTORY_ADDRESS): UniswapDayData { + const uniswap = Factory.load(factoryAddress)! const timestamp = event.block.timestamp.toI32() const dayID = timestamp / 86400 // rounded const dayStartTimestamp = dayID * 86400 @@ -72,6 +72,7 @@ export function updatePoolDayData(event: ethereum.Event): PoolDayData { poolDayData.sqrtPrice = pool.sqrtPrice poolDayData.token0Price = pool.token0Price poolDayData.token1Price = pool.token1Price + poolDayData.close = pool.token0Price poolDayData.tick = pool.tick poolDayData.tvlUSD = pool.totalValueLockedUSD poolDayData.txCount = poolDayData.txCount.plus(ONE_BI) diff --git a/src/utils/pricing.ts b/src/utils/pricing.ts index 7d63f642..eb62db24 100644 --- a/src/utils/pricing.ts +++ b/src/utils/pricing.ts @@ -30,7 +30,7 @@ export const WHITELIST_TOKENS: string[] = [ '0x956f47f50a910163d8bf957cf5846d573e7f87ca', // FEI '0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0', // MATIC '0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9', // AAVE - '0xfe2e637202056d30016725477c5da089ab0a043a' // sETH2 + '0xfe2e637202056d30016725477c5da089ab0a043a', // sETH2 ] const STABLE_COINS: string[] = [ @@ -39,7 +39,7 @@ const STABLE_COINS: string[] = [ '0xdac17f958d2ee523a2206206994597c13d831ec7', '0x0000000000085d4780b73119b644ae5ecd22b376', '0x956f47f50a910163d8bf957cf5846d573e7f87ca', - '0x4dd28568d05f09b02220b09c2cb307bfd837cb95' + '0x4dd28568d05f09b02220b09c2cb307bfd837cb95', ] const MINIMUM_ETH_LOCKED = BigDecimal.fromString('60') @@ -48,10 +48,7 @@ const Q192 = BigInt.fromI32(2).pow(192 as u8) export function sqrtPriceX96ToTokenPrices(sqrtPriceX96: BigInt, token0: Token, token1: Token): BigDecimal[] { const num = sqrtPriceX96.times(sqrtPriceX96).toBigDecimal() const denom = BigDecimal.fromString(Q192.toString()) - const price1 = num - .div(denom) - .times(exponentToBigDecimal(token0.decimals)) - .div(exponentToBigDecimal(token1.decimals)) + const price1 = num.div(denom).times(exponentToBigDecimal(token0.decimals)).div(exponentToBigDecimal(token1.decimals)) const price0 = safeDiv(BigDecimal.fromString('1'), price1) return [price0, price1] diff --git a/src/utils/staticTokenDefinition.ts b/src/utils/staticTokenDefinition.ts index 2c0b8720..35bd3aca 100644 --- a/src/utils/staticTokenDefinition.ts +++ b/src/utils/staticTokenDefinition.ts @@ -10,7 +10,7 @@ export class StaticTokenDefinition { export const getStaticDefinition = ( tokenAddress: Address, - staticDefinitions: Array, + staticDefinitions: Array ): StaticTokenDefinition | null => { const tokenAddressHex = tokenAddress.toHexString() diff --git a/src/utils/token.ts b/src/utils/token.ts index 1aca8117..15857b9f 100644 --- a/src/utils/token.ts +++ b/src/utils/token.ts @@ -8,7 +8,7 @@ import { getStaticDefinition, STATIC_TOKEN_DEFINITIONS, StaticTokenDefinition } export function fetchTokenSymbol( tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS ): string { const contract = ERC20.bind(tokenAddress) const contractSymbolBytes = ERC20SymbolBytes.bind(tokenAddress) @@ -39,7 +39,7 @@ export function fetchTokenSymbol( export function fetchTokenName( tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS ): string { const contract = ERC20.bind(tokenAddress) const contractNameBytes = ERC20NameBytes.bind(tokenAddress) @@ -80,7 +80,7 @@ export function fetchTokenTotalSupply(tokenAddress: Address): BigInt { export function fetchTokenDecimals( tokenAddress: Address, - staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS, + staticTokenDefinitions: StaticTokenDefinition[] = STATIC_TOKEN_DEFINITIONS ): BigInt | null { const contract = ERC20.bind(tokenAddress) // try types uint8 for decimals diff --git a/tests/handleBurn.test.ts b/tests/handleBurn.test.ts index 89ddb76d..a1a3409c 100644 --- a/tests/handleBurn.test.ts +++ b/tests/handleBurn.test.ts @@ -54,7 +54,7 @@ const BURN_EVENT = new Burn( new ethereum.EventParam('amount0', ethereum.Value.fromUnsignedBigInt(BURN_FIXTURE.amount0)), new ethereum.EventParam('amount1', ethereum.Value.fromUnsignedBigInt(BURN_FIXTURE.amount1)), ], - MOCK_EVENT.receipt, + MOCK_EVENT.receipt ) describe('handleBurn', () => { @@ -66,7 +66,7 @@ describe('handleBurn', () => { WETH_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + POOL_TICK_SPACING_03 ) const bundle = new Bundle('1') diff --git a/tests/handleCollect.test.ts b/tests/handleCollect.test.ts index 92f31db5..37f4c56e 100644 --- a/tests/handleCollect.test.ts +++ b/tests/handleCollect.test.ts @@ -54,7 +54,7 @@ const COLLECT_EVENT = new Collect( new ethereum.EventParam('amount0', ethereum.Value.fromUnsignedBigInt(COLLECT_FIXTURE.amount0)), new ethereum.EventParam('amount1', ethereum.Value.fromUnsignedBigInt(COLLECT_FIXTURE.amount1)), ], - MOCK_EVENT.receipt, + MOCK_EVENT.receipt ) describe('handleMint', () => { @@ -66,7 +66,7 @@ describe('handleMint', () => { WETH_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + POOL_TICK_SPACING_03 ) const bundle = new Bundle('1') @@ -90,11 +90,11 @@ describe('handleMint', () => { const collectedAmountToken0 = convertTokenToDecimal( COLLECT_FIXTURE.amount0, - BigInt.fromString(USDC_MAINNET_FIXTURE.decimals), + BigInt.fromString(USDC_MAINNET_FIXTURE.decimals) ) const collectedAmountToken1 = convertTokenToDecimal( COLLECT_FIXTURE.amount1, - BigInt.fromString(WETH_MAINNET_FIXTURE.decimals), + BigInt.fromString(WETH_MAINNET_FIXTURE.decimals) ) const collectedAmountETH = collectedAmountToken0 .times(TEST_USDC_DERIVED_ETH) diff --git a/tests/handleMint.test.ts b/tests/handleMint.test.ts index 195f0316..8c816dfe 100644 --- a/tests/handleMint.test.ts +++ b/tests/handleMint.test.ts @@ -57,7 +57,7 @@ const MINT_EVENT = new Mint( new ethereum.EventParam('amount0', ethereum.Value.fromUnsignedBigInt(MINT_FIXTURE.amount0)), new ethereum.EventParam('amount1', ethereum.Value.fromUnsignedBigInt(MINT_FIXTURE.amount1)), ], - MOCK_EVENT.receipt, + MOCK_EVENT.receipt ) describe('handleMint', () => { @@ -69,7 +69,7 @@ describe('handleMint', () => { WETH_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + POOL_TICK_SPACING_03 ) const bundle = new Bundle('1') diff --git a/tests/handlePoolCreated.test.ts b/tests/handlePoolCreated.test.ts index 801a67f6..8c88f406 100644 --- a/tests/handlePoolCreated.test.ts +++ b/tests/handlePoolCreated.test.ts @@ -31,7 +31,7 @@ describe('handlePoolCreated', () => { WETH_MAINNET_FIXTURE, USDC_WETH_03_MAINNET_POOL, POOL_FEE_TIER_03, - POOL_TICK_SPACING_03, + POOL_TICK_SPACING_03 ) assertObjectMatches('Factory', FACTORY_ADDRESS, [ diff --git a/tests/intervalUpdates.test.ts b/tests/intervalUpdates.test.ts new file mode 100644 index 00000000..39d00932 --- /dev/null +++ b/tests/intervalUpdates.test.ts @@ -0,0 +1,487 @@ +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 { + updatePoolDayData, + updatePoolHourData, + updateTokenDayData, + updateTokenHourData, + updateUniswapDayData, +} from '../src/utils/intervalUpdates' +import { + assertObjectMatches, + MOCK_EVENT, + MOCK_EVENT as poolEvent, + POOL_FEE_TIER_03, + TEST_ETH_PRICE_USD, + USDC_MAINNET_FIXTURE, + USDC_WETH_03_MAINNET_POOL, + WETH_MAINNET_FIXTURE, +} from './constants' + +describe('uniswap interval data', () => { + beforeEach(() => { + clearStore() + + const factory = new Factory(FACTORY_ADDRESS) + factory.poolCount = ZERO_BI + factory.totalVolumeUSD = ZERO_BD + factory.totalVolumeETH = ZERO_BD + factory.totalFeesUSD = ZERO_BD + factory.totalFeesETH = ZERO_BD + factory.untrackedVolumeUSD = ZERO_BD + factory.totalValueLockedUSDUntracked = ZERO_BD + factory.totalValueLockedETHUntracked = ZERO_BD + factory.totalValueLockedETH = ZERO_BD + factory.txCount = ZERO_BI + factory.totalValueLockedUSD = ZERO_BD + factory.owner = ADDRESS_ZERO + + factory.save() + }) + + 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 uniswapTxCount = BigInt.fromString('10') + const uniswapTotalValueLockedUSD = BigDecimal.fromString('100') + factory.txCount = uniswapTxCount + factory.totalValueLockedUSD = uniswapTotalValueLockedUSD + factory.save() + + updateUniswapDayData(poolEvent) + const dayId = poolEvent.block.timestamp.toI32() / 86400 + const dayStartTimestamp = dayId * 86400 + + assertObjectMatches('UniswapDayData', dayId.toString(), [ + ['date', dayStartTimestamp.toString()], + ['volumeETH', '0'], + ['volumeUSD', '0'], + ['volumeUSDUntracked', '0'], + ['feesUSD', '0'], + ['tvlUSD', uniswapTotalValueLockedUSD.toString()], + ['txCount', uniswapTxCount.toString()], + ]) + + const updatedTxCount = BigInt.fromString('20') + factory.txCount = updatedTxCount + factory.save() + + updateUniswapDayData(poolEvent) + + assertObjectMatches('UniswapDayData', dayId.toString(), [['txCount', updatedTxCount.toString()]]) + }) +}) + +describe('pool interval data', () => { + beforeEach(() => { + clearStore() + + const pool = new Pool(USDC_WETH_03_MAINNET_POOL) + pool.createdAtTimestamp = ZERO_BI + pool.createdAtBlockNumber = ZERO_BI + pool.token0 = USDC_MAINNET_FIXTURE.address + pool.token1 = WETH_MAINNET_FIXTURE.address + pool.feeTier = BigInt.fromI32(POOL_FEE_TIER_03) + pool.liquidity = ZERO_BI + pool.sqrtPrice = ZERO_BI + pool.token0Price = ZERO_BD + pool.token1Price = ZERO_BD + pool.tick = ZERO_BI + pool.observationIndex = ZERO_BI + pool.volumeToken0 = ZERO_BD + pool.volumeToken1 = ZERO_BD + pool.volumeUSD = ZERO_BD + pool.untrackedVolumeUSD = ZERO_BD + pool.feesUSD = ZERO_BD + pool.txCount = ZERO_BI + pool.collectedFeesToken0 = ZERO_BD + pool.collectedFeesToken1 = ZERO_BD + pool.collectedFeesUSD = ZERO_BD + pool.totalValueLockedToken0 = ZERO_BD + pool.totalValueLockedToken1 = ZERO_BD + pool.totalValueLockedUSD = ZERO_BD + pool.totalValueLockedETH = ZERO_BD + pool.totalValueLockedUSDUntracked = ZERO_BD + pool.liquidityProviderCount = ZERO_BI + + pool.save() + }) + + test('success - create and update poolDayData', () => { + const pool = Pool.load(USDC_WETH_03_MAINNET_POOL)! + pool.token0Price = BigDecimal.fromString('1') + pool.token1Price = BigDecimal.fromString('2') + pool.liquidity = BigInt.fromString('100') + pool.sqrtPrice = BigInt.fromString('200') + pool.tick = BigInt.fromString('300') + pool.totalValueLockedUSD = BigDecimal.fromString('1000') + pool.save() + + const poolEvent = MOCK_EVENT + poolEvent.address = Address.fromString(USDC_WETH_03_MAINNET_POOL) + + updatePoolDayData(poolEvent) + + const dayId = poolEvent.block.timestamp.toI32() / 86400 + const dayStartTimestamp = dayId * 86400 + const dayPoolID = poolEvent.address.toHexString().concat('-').concat(dayId.toString()) + + assertObjectMatches('PoolDayData', dayPoolID, [ + ['date', dayStartTimestamp.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '1'], + ['open', '1'], + ['high', '1'], + ['low', '1'], + ['close', '1'], + ['token0Price', '1'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + + // update the high price + pool.token0Price = BigDecimal.fromString('2') + pool.save() + + updatePoolDayData(poolEvent) + + assertObjectMatches('PoolDayData', dayPoolID, [ + ['date', dayStartTimestamp.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '2'], + ['open', '1'], + ['high', '2'], + ['low', '1'], + ['close', '2'], + ['token0Price', '2'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + + // update the low price + pool.token0Price = BigDecimal.fromString('0') + pool.save() + + updatePoolDayData(poolEvent) + + assertObjectMatches('PoolDayData', dayPoolID, [ + ['date', dayStartTimestamp.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '3'], + ['open', '1'], + ['high', '2'], + ['low', '0'], + ['close', '0'], + ['token0Price', '0'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + }) + + test('success - create and update poolHourData', () => { + const pool = Pool.load(USDC_WETH_03_MAINNET_POOL)! + pool.token0Price = BigDecimal.fromString('1') + pool.token1Price = BigDecimal.fromString('2') + pool.liquidity = BigInt.fromString('100') + pool.sqrtPrice = BigInt.fromString('200') + pool.tick = BigInt.fromString('300') + pool.totalValueLockedUSD = BigDecimal.fromString('1000') + pool.save() + + const poolEvent = MOCK_EVENT + poolEvent.address = Address.fromString(USDC_WETH_03_MAINNET_POOL) + + updatePoolHourData(poolEvent) + + const hourIndex = poolEvent.block.timestamp.toI32() / 3600 + const hourStartUnix = hourIndex * 3600 + const hourPoolID = poolEvent.address.toHexString().concat('-').concat(hourIndex.toString()) + + assertObjectMatches('PoolHourData', hourPoolID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '1'], + ['open', '1'], + ['high', '1'], + ['low', '1'], + ['close', '1'], + ['token0Price', '1'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + + // update the high price + pool.token0Price = BigDecimal.fromString('2') + pool.save() + + updatePoolHourData(poolEvent) + + assertObjectMatches('PoolHourData', hourPoolID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '2'], + ['open', '1'], + ['high', '2'], + ['low', '1'], + ['close', '2'], + ['token0Price', '2'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + + // update the low price + pool.token0Price = BigDecimal.fromString('0') + pool.save() + + updatePoolHourData(poolEvent) + + assertObjectMatches('PoolHourData', hourPoolID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['pool', USDC_WETH_03_MAINNET_POOL], + ['volumeToken0', '0'], + ['volumeToken1', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['txCount', '3'], + ['open', '1'], + ['high', '2'], + ['low', '0'], + ['close', '0'], + ['token0Price', '0'], + ['token1Price', '2'], + ['liquidity', '100'], + ['sqrtPrice', '200'], + ['tick', '300'], + ['tvlUSD', '1000'], + ]) + }) +}) + +describe('token interval data', () => { + beforeEach(() => { + clearStore() + + const token = new Token(WETH_MAINNET_FIXTURE.address) + token.symbol = WETH_MAINNET_FIXTURE.symbol + token.name = WETH_MAINNET_FIXTURE.name + token.decimals = BigInt.fromString(WETH_MAINNET_FIXTURE.decimals) + token.totalSupply = BigInt.fromString(WETH_MAINNET_FIXTURE.totalSupply) + token.volume = ZERO_BD + token.volumeUSD = ZERO_BD + token.untrackedVolumeUSD = ZERO_BD + token.feesUSD = ZERO_BD + token.txCount = ZERO_BI + token.poolCount = ZERO_BI + token.totalValueLocked = ZERO_BD + token.totalValueLockedUSD = ZERO_BD + token.totalValueLockedUSDUntracked = ZERO_BD + token.derivedETH = ZERO_BD + token.whitelistPools = [] + + token.save() + + const bundle = new Bundle('1') + bundle.ethPriceUSD = ZERO_BD + bundle.save() + }) + + test('success - create and update tokenDayData', () => { + const token = Token.load(WETH_MAINNET_FIXTURE.address)! + token.derivedETH = BigDecimal.fromString('1') + token.totalValueLocked = BigDecimal.fromString('100') + token.totalValueLockedUSD = BigDecimal.fromString('1000') + token.save() + + const bundle = Bundle.load('1')! + bundle.ethPriceUSD = TEST_ETH_PRICE_USD + bundle.save() + + updateTokenDayData(token, MOCK_EVENT) + + const dayId = MOCK_EVENT.block.timestamp.toI32() / 86400 + const dayStartTimestamp = dayId * 86400 + const tokenDayID = token.id.toString().concat('-').concat(dayId.toString()) + + assertObjectMatches('TokenDayData', tokenDayID, [ + ['date', dayStartTimestamp.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', TEST_ETH_PRICE_USD.toString()], + ['low', TEST_ETH_PRICE_USD.toString()], + ['close', TEST_ETH_PRICE_USD.toString()], + ['priceUSD', TEST_ETH_PRICE_USD.toString()], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + + // update the high price + token.derivedETH = BigDecimal.fromString('2') + token.save() + + const highPriceStr = TEST_ETH_PRICE_USD.times(BigDecimal.fromString('2')).toString() + + updateTokenDayData(token, MOCK_EVENT) + + assertObjectMatches('TokenDayData', tokenDayID, [ + ['date', dayStartTimestamp.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', highPriceStr], + ['low', TEST_ETH_PRICE_USD.toString()], + ['close', highPriceStr], + ['priceUSD', highPriceStr], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + + // update the low price + token.derivedETH = ZERO_BD + token.save() + const lowPriceStr = ZERO_BD.toString() + + updateTokenDayData(token, MOCK_EVENT) + + assertObjectMatches('TokenDayData', tokenDayID, [ + ['date', dayStartTimestamp.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', highPriceStr], + ['low', lowPriceStr], + ['close', lowPriceStr], + ['priceUSD', lowPriceStr], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + }) + + test('success - create and update tokenHourData', () => { + const token = Token.load(WETH_MAINNET_FIXTURE.address)! + token.derivedETH = BigDecimal.fromString('1') + token.totalValueLocked = BigDecimal.fromString('100') + token.totalValueLockedUSD = BigDecimal.fromString('1000') + token.save() + + const bundle = Bundle.load('1')! + bundle.ethPriceUSD = TEST_ETH_PRICE_USD + bundle.save() + + updateTokenHourData(token, MOCK_EVENT) + + const hourIndex = MOCK_EVENT.block.timestamp.toI32() / 3600 + const hourStartUnix = hourIndex * 3600 + const tokenHourID = token.id.toString().concat('-').concat(hourIndex.toString()) + + assertObjectMatches('TokenHourData', tokenHourID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', TEST_ETH_PRICE_USD.toString()], + ['low', TEST_ETH_PRICE_USD.toString()], + ['close', TEST_ETH_PRICE_USD.toString()], + ['priceUSD', TEST_ETH_PRICE_USD.toString()], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + + // update the high price + token.derivedETH = BigDecimal.fromString('2') + token.save() + + const highPriceStr = TEST_ETH_PRICE_USD.times(BigDecimal.fromString('2')).toString() + + updateTokenHourData(token, MOCK_EVENT) + + assertObjectMatches('TokenHourData', tokenHourID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', highPriceStr], + ['low', TEST_ETH_PRICE_USD.toString()], + ['close', highPriceStr], + ['priceUSD', highPriceStr], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + + // update the low price + token.derivedETH = ZERO_BD + token.save() + const lowPriceStr = ZERO_BD.toString() + + updateTokenHourData(token, MOCK_EVENT) + + assertObjectMatches('TokenHourData', tokenHourID, [ + ['periodStartUnix', hourStartUnix.toString()], + ['token', WETH_MAINNET_FIXTURE.address], + ['volume', '0'], + ['volumeUSD', '0'], + ['feesUSD', '0'], + ['untrackedVolumeUSD', '0'], + ['open', TEST_ETH_PRICE_USD.toString()], + ['high', highPriceStr], + ['low', lowPriceStr], + ['close', lowPriceStr], + ['priceUSD', lowPriceStr], + ['totalValueLocked', '100'], + ['totalValueLockedUSD', '1000'], + ]) + }) +})