Bug fixes from smoke testing (#238)

* Fix update for entity relations.

* Implement demo values in uni-info-watcher indexer code.

* amend

Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
Ashwin Phatak 2021-08-31 18:05:29 +05:30 committed by GitHub
parent f1f70ad7d4
commit fc4f49113b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 100 additions and 34 deletions

View File

@ -48,6 +48,7 @@ Create the databases for the job queues and enable the `pgcrypto` extension on t
```
createdb address-watcher-job-queue
createdb uni-watcher-job-queue
createdb uni-info-watcher-job-queue
```
```
@ -74,6 +75,18 @@ CREATE EXTENSION
uni-watcher-job-queue=# exit
```
```
postgres@tesla:~$ psql -U postgres -h localhost uni-info-watcher-job-queue
Password for user postgres:
psql (12.7 (Ubuntu 12.7-1.pgdg18.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, bits: 256, compression: off)
Type "help" for help.
uni-info-watcher-job-queue=# CREATE EXTENSION pgcrypto;
CREATE EXTENSION
uni-info-watcher-job-queue=# exit
```
#### Reset
Reset the databases used by the watchers:

View File

@ -7,7 +7,8 @@ import yargs from 'yargs';
import 'reflect-metadata';
import { ethers } from 'ethers';
import { Config, getConfig } from '../config';
import { Config, getConfig } from '@vulcanize/util';
import { Database } from '../database';
(async () => {

View File

@ -463,8 +463,11 @@ export class Indexer implements IndexerInterface {
token0.whitelistPools.push(pool);
}
await this._db.saveToken(dbTx, token0, block);
await this._db.saveToken(dbTx, token1, block);
token0 = await this._db.saveToken(dbTx, token0, block);
token1 = await this._db.saveToken(dbTx, token1, block);
pool.token0 = token0;
pool.token1 = token1;
await this._db.savePool(dbTx, pool, block);
await this._db.saveFactory(dbTx, factory, block);
await dbTx.commitTransaction();
} catch (error) {
@ -511,7 +514,7 @@ export class Indexer implements IndexerInterface {
// Update ETH price now that prices could have changed.
const bundle = await this._db.getBundle(dbTx, { id: '1', blockHash: block.hash });
assert(bundle);
bundle.ethPriceUSD = await getEthPriceInUSD(this._db, dbTx, block);
bundle.ethPriceUSD = await getEthPriceInUSD(this._db, dbTx, block, this._isDemo);
// Update token prices.
const [token0, token1] = await Promise.all([
@ -521,11 +524,13 @@ export class Indexer implements IndexerInterface {
assert(token0 && token1, 'Pool tokens not found.');
token0.derivedETH = await findEthPerToken(token0);
token1.derivedETH = await findEthPerToken(token1);
token0.derivedETH = await findEthPerToken(this._db, dbTx, token0, this._isDemo);
token1.derivedETH = await findEthPerToken(this._db, dbTx, token1, this._isDemo);
this._db.savePool(dbTx, pool, block);
this._db.saveBundle(dbTx, bundle, block);
pool.token0 = token0;
pool.token1 = token1;
await this._db.savePool(dbTx, pool, block);
await this._db.saveBundle(dbTx, bundle, block);
await updatePoolDayData(this._db, dbTx, { contractAddress, block });
await updatePoolHourData(this._db, dbTx, { contractAddress, block });
@ -551,15 +556,17 @@ export class Indexer implements IndexerInterface {
const bundle = await this._db.getBundle(dbTx, { id: '1', blockHash: block.hash });
assert(bundle);
const poolAddress = contractAddress;
const pool = await this._db.getPool(dbTx, { id: poolAddress, blockHash: block.hash });
let pool = await this._db.getPool(dbTx, { id: poolAddress, blockHash: block.hash });
assert(pool);
// TODO: In subgraph factory is fetched by hardcoded factory address.
// Currently fetching first factory in database as only one exists.
const [factory] = await this._db.getModelEntities(dbTx, Factory, { hash: block.hash }, {}, { limit: 1 });
const token0 = pool.token0;
const token1 = pool.token1;
let token0 = await this._db.getToken(dbTx, pool.token0);
let token1 = await this._db.getToken(dbTx, pool.token1);
assert(token0);
assert(token1);
const amount0 = convertTokenToDecimal(BigInt(mintEvent.amount0), BigInt(token0.decimals));
const amount1 = convertTokenToDecimal(BigInt(mintEvent.amount1), BigInt(token1.decimals));
@ -664,16 +671,24 @@ export class Indexer implements IndexerInterface {
await updatePoolDayData(this._db, dbTx, { block, contractAddress });
await updatePoolHourData(this._db, dbTx, { block, contractAddress });
await Promise.all([
[token0, token1] = await Promise.all([
this._db.saveToken(dbTx, token0, block),
this._db.saveToken(dbTx, token1, block)
]);
await this._db.savePool(dbTx, pool, block);
pool.token0 = token0;
pool.token1 = token1;
pool = await this._db.savePool(dbTx, pool, block);
await this._db.saveFactory(dbTx, factory, block);
mint.pool = pool;
mint.token0 = token0;
mint.token1 = token1;
await this._db.saveMint(dbTx, mint, block);
lowerTick.pool = pool;
upperTick.pool = pool;
await Promise.all([
await this._db.saveTick(dbTx, lowerTick, block),
await this._db.saveTick(dbTx, upperTick, block)
@ -696,15 +711,17 @@ export class Indexer implements IndexerInterface {
const bundle = await this._db.getBundle(dbTx, { id: '1', blockHash: block.hash });
assert(bundle);
const poolAddress = contractAddress;
const pool = await this._db.getPool(dbTx, { id: poolAddress, blockHash: block.hash });
let pool = await this._db.getPool(dbTx, { id: poolAddress, blockHash: block.hash });
assert(pool);
// TODO: In subgraph factory is fetched by hardcoded factory address.
// Currently fetching first factory in database as only one exists.
const [factory] = await this._db.getModelEntities(dbTx, Factory, { hash: block.hash }, {}, { limit: 1 });
const token0 = pool.token0;
const token1 = pool.token1;
let token0 = await this._db.getToken(dbTx, pool.token0);
let token1 = await this._db.getToken(dbTx, pool.token1);
assert(token0);
assert(token1);
const amount0 = convertTokenToDecimal(BigInt(burnEvent.amount0), BigInt(token0.decimals));
const amount1 = convertTokenToDecimal(BigInt(burnEvent.amount1), BigInt(token1.decimals));
@ -794,21 +811,28 @@ export class Indexer implements IndexerInterface {
await updatePoolDayData(this._db, dbTx, { block, contractAddress });
await updatePoolHourData(this._db, dbTx, { block, contractAddress });
await Promise.all([
[token0, token1] = await Promise.all([
this._db.saveToken(dbTx, token0, block),
this._db.saveToken(dbTx, token1, block)
]);
await this._db.savePool(dbTx, pool, block);
pool.token0 = token0;
pool.token1 = token1;
pool = await this._db.savePool(dbTx, pool, block);
await this._db.saveFactory(dbTx, factory, block);
// Skipping update Tick fee and Tick day data as they are not queried.
lowerTick.pool = pool;
upperTick.pool = pool;
await Promise.all([
await this._db.saveTick(dbTx, lowerTick, block),
await this._db.saveTick(dbTx, upperTick, block)
]);
burn.pool = pool;
burn.token0 = token0;
burn.token1 = token1;
await this._db.saveBurn(dbTx, burn, block);
await dbTx.commitTransaction();
} catch (error) {
@ -823,14 +847,14 @@ export class Indexer implements IndexerInterface {
const dbTx = await this._db.createTransactionRunner();
try {
const bundle = await this._db.getBundle(dbTx, { id: '1', blockHash: block.hash });
let bundle = await this._db.getBundle(dbTx, { id: '1', blockHash: block.hash });
assert(bundle);
// TODO: In subgraph factory is fetched by hardcoded factory address.
// Currently fetching first factory in database as only one exists.
const [factory] = await this._db.getModelEntities(dbTx, Factory, { hash: block.hash }, {}, { limit: 1 });
const pool = await this._db.getPool(dbTx, { id: contractAddress, blockHash: block.hash });
let pool = await this._db.getPool(dbTx, { id: contractAddress, blockHash: block.hash });
assert(pool);
// Hot fix for bad pricing.
@ -838,7 +862,7 @@ export class Indexer implements IndexerInterface {
return;
}
const [token0, token1] = await Promise.all([
let [token0, token1] = await Promise.all([
this._db.getToken(dbTx, { id: pool.token0.id, blockHash: block.hash }),
this._db.getToken(dbTx, { id: pool.token1.id, blockHash: block.hash })
]);
@ -924,9 +948,10 @@ export class Indexer implements IndexerInterface {
pool.token1Price = prices[1];
// Update USD pricing.
bundle.ethPriceUSD = await getEthPriceInUSD(this._db, dbTx, block);
token0.derivedETH = await findEthPerToken(token0);
token1.derivedETH = await findEthPerToken(token1);
bundle.ethPriceUSD = await getEthPriceInUSD(this._db, dbTx, block, this._isDemo);
bundle = await this._db.saveBundle(dbTx, bundle, block);
token0.derivedETH = await findEthPerToken(this._db, dbTx, token0, this._isDemo);
token1.derivedETH = await findEthPerToken(this._db, dbTx, token1, this._isDemo);
/**
* Things afffected by new USD rates.
@ -1008,16 +1033,31 @@ export class Indexer implements IndexerInterface {
token1HourData.untrackedVolumeUSD = token1HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked);
token1HourData.feesUSD = token1HourData.feesUSD.plus(feesUSD);
await this._db.saveBundle(dbTx, bundle, block);
await this._db.saveFactory(dbTx, factory, block);
[token0, token1] = await Promise.all([
this._db.saveToken(dbTx, token0, block),
this._db.saveToken(dbTx, token1, block)
]);
pool.token0 = token0;
pool.token1 = token1;
pool = await this._db.savePool(dbTx, pool, block);
swap.token0 = token0;
swap.token1 = token1;
swap.pool = pool;
await this._db.saveSwap(dbTx, swap, block);
token0DayData.token = token0;
token1DayData.token = token1;
await this._db.saveTokenDayData(dbTx, token0DayData, block);
await this._db.saveTokenDayData(dbTx, token1DayData, block);
await this._db.saveUniswapDayData(dbTx, uniswapDayData, block);
poolDayData.pool = pool;
await this._db.savePoolDayData(dbTx, poolDayData, block);
await this._db.saveFactory(dbTx, factory, block);
await this._db.savePool(dbTx, pool, block);
await this._db.saveToken(dbTx, token0, block);
await this._db.saveToken(dbTx, token1, block);
// Skipping update of inner vars of current or crossed ticks as they are not queried.
await dbTx.commitTransaction();

View File

@ -117,7 +117,7 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
tokens: async (_: any, { block = {}, first, orderBy, orderDirection, where }: { block: BlockHeight, first: number, orderBy: string, orderDirection: OrderDirection, where: { [key: string]: any } }) => {
log('tokens', orderBy, orderDirection, where);
return indexer.getEntities(Token, block, where, { limit: first, orderBy, orderDirection });
return indexer.getEntities(Token, block, where, { limit: first, orderBy, orderDirection }, ['token.whitelistPools']);
},
tokenDayDatas: async (_: any, { first, skip, orderBy, orderDirection, where }: { first: number, skip: number, orderBy: string, orderDirection: OrderDirection, where: { [key: string]: any } }) => {

View File

@ -120,6 +120,7 @@ type Token {
txCount: BigInt!
volume: BigDecimal!
volumeUSD: BigDecimal!
whitelistPools: [Pool]
}
type TokenDayData {

View File

@ -46,6 +46,9 @@ export const WHITELIST_TOKENS: string[] = [
const MINIMUM_ETH_LOCKED = new Decimal(52);
const Q192 = 2 ** 192;
// Constants used in demo.
const ETH_PRICE_IN_USD = '3200.00';
export const sqrtPriceX96ToTokenPrices = (sqrtPriceX96: bigint, token0: Token, token1: Token): Decimal[] => {
const num = new Decimal((sqrtPriceX96 * sqrtPriceX96).toString());
const denom = new Decimal(Q192.toString());
@ -60,7 +63,13 @@ export const sqrtPriceX96ToTokenPrices = (sqrtPriceX96: bigint, token0: Token, t
return [price0, price1];
};
export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: Block): Promise<Decimal> => {
export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: Block, isDemo: boolean): Promise<Decimal> => {
if (isDemo) {
// For demo purpose in local development.
const ethPriceInUSD = new Decimal(ETH_PRICE_IN_USD);
return ethPriceInUSD;
}
// Fetch eth prices for each stablecoin.
const usdcPool = await db.getPool(dbTx, { id: USDC_WETH_03_POOL, blockHash: block.hash }); // DAI is token0.
@ -75,8 +84,8 @@ export const getEthPriceInUSD = async (db: Database, dbTx: QueryRunner, block: B
* Search through graph to find derived Eth per token.
* @todo update to be derived ETH (add stablecoin estimates)
**/
export const findEthPerToken = async (token: Token): Promise<Decimal> => {
if (token.id === WETH_ADDRESS) {
export const findEthPerToken = async (db: Database, dbTx: QueryRunner, token: Token, isDemo: boolean): Promise<Decimal> => {
if (token.id === WETH_ADDRESS || isDemo) {
return new Decimal(1);
}
@ -87,7 +96,9 @@ export const findEthPerToken = async (token: Token): Promise<Decimal> => {
let priceSoFar = new Decimal(0);
for (let i = 0; i < whiteList.length; ++i) {
const pool = whiteList[i];
const poolAddress = whiteList[i].id;
const pool = await db.getPool(dbTx, { id: poolAddress });
assert(pool);
if (BigNumber.from(pool.liquidity).gt(0)) {
if (pool.token0.id === token.id) {