diff --git a/packages/uni-info-watcher/.eslintrc.json b/packages/uni-info-watcher/.eslintrc.json index cfbe0109..853d994a 100644 --- a/packages/uni-info-watcher/.eslintrc.json +++ b/packages/uni-info-watcher/.eslintrc.json @@ -26,7 +26,7 @@ }, "overrides": [ { - "files": ["*.test.ts"], + "files": ["*.test.ts", "test/*.ts"], "rules": { "no-unused-expressions": "off" } diff --git a/packages/uni-info-watcher/package.json b/packages/uni-info-watcher/package.json index 5926fb24..a956ed8d 100644 --- a/packages/uni-info-watcher/package.json +++ b/packages/uni-info-watcher/package.json @@ -15,9 +15,9 @@ "typeorm": "^0.2.32" }, "scripts": { - "server": "DEBUG=vulcanize:* nodemon src/server.ts -f environments/local.toml", + "server": "DEBUG=vulcanize:* nodemon --watch src src/server.ts -f environments/local.toml", "server:mock": "MOCK=1 nodemon src/server.ts -f environments/local.toml", - "job-runner": "DEBUG=vulcanize:* nodemon src/job-runner.ts -f environments/local.toml", + "job-runner": "DEBUG=vulcanize:* nodemon --watch src src/job-runner.ts -f environments/local.toml", "test": "mocha -r ts-node/register src/**/*.spec.ts", "lint": "eslint .", "build": "tsc", diff --git a/packages/uni-info-watcher/src/smoke.test.ts b/packages/uni-info-watcher/src/smoke.test.ts index 46a94d32..af512187 100644 --- a/packages/uni-info-watcher/src/smoke.test.ts +++ b/packages/uni-info-watcher/src/smoke.test.ts @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { ethers, Contract, ContractTransaction, Signer } from 'ethers'; +import { ethers, Contract, Signer } from 'ethers'; import { request } from 'graphql-request'; import 'mocha'; import _ from 'lodash'; @@ -32,10 +32,15 @@ import { queryToken, queryPoolsByTokens, queryPoolById, - queryPoolDayData, queryMints, queryTicks } from '../test/queries'; +import { + checkUniswapDayData, + checkPoolDayData, + checkTokenDayData, + checkTokenHourData +} from '../test/utils'; const NETWORK_RPC_URL = 'http://localhost:8545'; @@ -92,7 +97,7 @@ describe('uni-info-watcher', () => { }); describe('PoolCreatedEvent', () => { - // NOTE Skipping checking entity updates that cannot be gotten using queries. + // NOTE Skipping checking entity updates that cannot be gotten/derived using queries. const fee = 500; @@ -114,6 +119,7 @@ describe('uni-info-watcher', () => { it('should trigger PoolCreatedEvent', async () => { // Create Pool. + // Not doing tx.wait() here as we are waiting for the event. createPool(factory, token0Address, token1Address, fee); // Wait for PoolCreatedEvent. @@ -182,29 +188,7 @@ describe('uni-info-watcher', () => { }); it('should update PoolDayData entity', async () => { - // Get the latest PoolDayData. - const variables = { - first: 1, - orderBy: 'date', - orderDirection: 'desc', - pool: pool.address - }; - const data = await request(endpoint, queryPoolDayData, variables); - expect(data.poolDayDatas).to.not.be.empty; - - const dayPoolID: string = data.poolDayDatas[0].id; - const poolID: string = dayPoolID.split('-')[0]; - const dayID: number = +dayPoolID.split('-')[1]; - const date = data.poolDayDatas[0].date; - const tvlUSD = data.poolDayDatas[0].tvlUSD; - - const dayStartTimestamp = dayID * 86400; - const poolData = await request(endpoint, queryPoolById, { id: pool.address }); - const totalValueLockedUSD: string = poolData.pool.totalValueLockedUSD; - - expect(poolID).to.be.equal(pool.address); - expect(date).to.be.equal(dayStartTimestamp); - expect(tvlUSD).to.be.equal(totalValueLockedUSD); + checkPoolDayData(endpoint, pool.address); }); }); @@ -251,8 +235,7 @@ describe('uni-info-watcher', () => { it('should trigger MintEvent', async () => { // Pool mint. - const transaction: ContractTransaction = await poolCallee.mint(pool.address, recipient, BigInt(tickLower), BigInt(tickUpper), BigInt(amount)); - await transaction.wait(); + poolCallee.mint(pool.address, recipient, BigInt(tickLower), BigInt(tickUpper), BigInt(amount)); // Wait for MintEvent. const eventType = 'MintEvent'; @@ -317,15 +300,18 @@ describe('uni-info-watcher', () => { const id: string = data.mints[0].id; const txCountID = id.split('#')[1]; + const origin = data.mints[0].origin; const owner = data.mints[0].owner; const sender = data.mints[0].sender; data = await request(endpoint, queryPoolById, { id: pool.address }); const poolTxCount = data.pool.txCount; + const expectedOrigin = recipient; const expectedOwner = recipient; const expectedSender = poolCallee.address; expect(txCountID).to.be.equal(poolTxCount); + expect(origin).to.be.equal(expectedOrigin); expect(owner).to.be.equal(expectedOwner); expect(sender).to.be.equal(expectedSender); }); @@ -343,5 +329,23 @@ describe('uni-info-watcher', () => { expect(upperTick.liquidityGross).to.be.equal(amount.toString()); expect(upperTick.liquidityNet).to.be.equal(amount.toString()); }); + + it('should update UniswapDayData entity', async () => { + checkUniswapDayData(endpoint); + }); + + it('should update PoolDayData entity', async () => { + checkPoolDayData(endpoint, pool.address); + }); + + it('should update TokenDayData entities', async () => { + checkTokenDayData(endpoint, token0.address); + checkTokenDayData(endpoint, token1.address); + }); + + it('should update TokenHourData entities', async () => { + checkTokenHourData(endpoint, token0.address); + checkTokenHourData(endpoint, token1.address); + }); }); }); diff --git a/packages/uni-info-watcher/test/queries.ts b/packages/uni-info-watcher/test/queries.ts index f4534098..18c32e38 100644 --- a/packages/uni-info-watcher/test/queries.ts +++ b/packages/uni-info-watcher/test/queries.ts @@ -65,6 +65,16 @@ query queryPoolsByTokens($tokens: [String!]) { } }`; +// Getting UniswapDayData(s). +export const queryUniswapDayData = gql` +query queryUniswapDayData($first: Int, $orderBy: UniswapDayData_orderBy, $orderDirection: OrderDirection) { + uniswapDayDatas(first: $first, orderBy: $orderBy, orderDirection: $orderDirection) { + id, + date, + tvlUSD + } +}`; + // Getting PoolDayData(s) filtered by pool and ordered by date. export const queryPoolDayData = gql` query queryPoolDayData($first: Int, $orderBy: PoolDayData_orderBy, $orderDirection: OrderDirection, $pool: String) { @@ -75,6 +85,29 @@ query queryPoolDayData($first: Int, $orderBy: PoolDayData_orderBy, $orderDirecti } }`; +// Getting TokenDayDatas(s) filtered by token and ordered by date. +export const queryTokenDayData = gql` +query queryTokenDayData($first: Int, $orderBy: TokenDayData_orderBy, $orderDirection: OrderDirection, $token: String) { + tokenDayDatas(first: $first, orderBy: $orderBy, orderDirection: $orderDirection, where: { token: $token }) { + id, + date, + totalValueLockedUSD + } +}`; + +// Getting TokenDayDatas(s) filtered by token and ordered by date. +export const queryTokenHourData = gql` +query queryTokenHourData($first: Int, $orderBy: TokenHourData_orderBy, $orderDirection: OrderDirection, $token: String) { + tokenHourDatas(first: $first, orderBy: $orderBy, orderDirection: $orderDirection, where: { token: $token }) { + id, + low, + high, + open, + close, + periodStartUnix + } +}`; + // Getting mint(s) filtered by pool, tokens and ordered by timestamp. export const queryMints = gql` query queryMints( diff --git a/packages/uni-info-watcher/test/utils.ts b/packages/uni-info-watcher/test/utils.ts new file mode 100644 index 00000000..bbd12fb7 --- /dev/null +++ b/packages/uni-info-watcher/test/utils.ts @@ -0,0 +1,122 @@ +import { expect } from 'chai'; +import { request } from 'graphql-request'; +import Decimal from 'decimal.js'; + +import { + queryFactory, + queryBundle, + queryToken, + queryPoolById, + queryPoolDayData, + queryUniswapDayData, + queryTokenDayData, + queryTokenHourData +} from '../test/queries'; + +export const checkUniswapDayData = async (endpoint: string): Promise => { + // Get the latest UniswapDayData. + const variables = { + first: 1, + orderBy: 'date', + orderDirection: 'desc' + }; + const data = await request(endpoint, queryUniswapDayData, variables); + expect(data.uniswapDayDatas).to.not.be.empty; + + const id: string = data.uniswapDayDatas[0].id; + const dayID = Number(id); + const date = data.uniswapDayDatas[0].date; + const tvlUSD = data.uniswapDayDatas[0].tvlUSD; + + const dayStartTimestamp = dayID * 86400; + const factoryData = await request(endpoint, queryFactory); + const totalValueLockedUSD: string = factoryData.factories[0].totalValueLockedUSD; + + expect(date).to.be.equal(dayStartTimestamp); + expect(tvlUSD).to.be.equal(totalValueLockedUSD); +}; + +export const checkPoolDayData = async (endpoint: string, poolAddress: string): Promise => { + // Get the latest PoolDayData. + const variables = { + first: 1, + orderBy: 'date', + orderDirection: 'desc', + pool: poolAddress + }; + const data = await request(endpoint, queryPoolDayData, variables); + expect(data.poolDayDatas).to.not.be.empty; + + const dayPoolID: string = data.poolDayDatas[0].id; + const poolID: string = dayPoolID.split('-')[0]; + const dayID = Number(dayPoolID.split('-')[1]); + const date = data.poolDayDatas[0].date; + const tvlUSD = data.poolDayDatas[0].tvlUSD; + + const dayStartTimestamp = dayID * 86400; + const poolData = await request(endpoint, queryPoolById, { id: poolAddress }); + const totalValueLockedUSD: string = poolData.pool.totalValueLockedUSD; + + expect(poolID).to.be.equal(poolAddress); + expect(date).to.be.equal(dayStartTimestamp); + expect(tvlUSD).to.be.equal(totalValueLockedUSD); +}; + +export const checkTokenDayData = async (endpoint: string, tokenAddress: string): Promise => { + // Get the latest TokenDayData. + const variables = { + first: 1, + orderBy: 'date', + orderDirection: 'desc', + token: tokenAddress + }; + const data = await request(endpoint, queryTokenDayData, variables); + expect(data.tokenDayDatas).to.not.be.empty; + + const tokenDayID: string = data.tokenDayDatas[0].id; + const tokenID: string = tokenDayID.split('-')[0]; + const dayID = Number(tokenDayID.split('-')[1]); + const date = data.tokenDayDatas[0].date; + const tvlUSD = data.tokenDayDatas[0].totalValueLockedUSD; + + const dayStartTimestamp = dayID * 86400; + const tokenData = await request(endpoint, queryToken, { id: tokenAddress }); + const totalValueLockedUSD: string = tokenData.token.totalValueLockedUSD; + + expect(tokenID).to.be.equal(tokenAddress); + expect(date).to.be.equal(dayStartTimestamp); + expect(tvlUSD).to.be.equal(totalValueLockedUSD); +}; + +export const checkTokenHourData = async (endpoint: string, tokenAddress: string): Promise => { + // Get the latest TokenHourData. + const variables = { + first: 1, + orderBy: 'periodStartUnix', + orderDirection: 'desc', + token: tokenAddress + }; + const data = await request(endpoint, queryTokenHourData, variables); + expect(data.tokenHourDatas).to.not.be.empty; + + const tokenHourID: string = data.tokenHourDatas[0].id; + const tokenID: string = tokenHourID.split('-')[0]; + const hourIndex = Number(tokenHourID.split('-')[1]); + const periodStartUnix = data.tokenHourDatas[0].periodStartUnix; + const low = data.tokenHourDatas[0].low; + const high = data.tokenHourDatas[0].high; + const open = data.tokenHourDatas[0].open; + const close = data.tokenHourDatas[0].close; + + const hourStartUnix = hourIndex * 3600; + const tokenData = await request(endpoint, queryToken, { id: tokenAddress }); + const bundleData = await request(endpoint, queryBundle); + const tokenPrice = new Decimal(tokenData.token.derivedETH).times(bundleData.bundles[0].ethPriceUSD); + + expect(tokenID).to.be.equal(tokenAddress); + expect(periodStartUnix).to.be.equal(hourStartUnix); + expect(low).to.be.equal(tokenPrice.toString()); + expect(high).to.be.equal(tokenPrice.toString()); + expect(open).to.be.equal(tokenPrice.toString()); + expect(close).to.be.equal(tokenPrice.toString()); +};