mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-24 03:59:06 +00:00
Handle Pool burn event. (#134)
Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
parent
3a6af9f9cc
commit
208b0f7f4f
@ -16,6 +16,7 @@ import { UniswapDayData } from './entity/UniswapDayData';
|
|||||||
import { Tick } from './entity/Tick';
|
import { Tick } from './entity/Tick';
|
||||||
import { TokenDayData } from './entity/TokenDayData';
|
import { TokenDayData } from './entity/TokenDayData';
|
||||||
import { TokenHourData } from './entity/TokenHourData';
|
import { TokenHourData } from './entity/TokenHourData';
|
||||||
|
import { Burn } from './entity/Burn';
|
||||||
|
|
||||||
export class Database {
|
export class Database {
|
||||||
_config: ConnectionOptions
|
_config: ConnectionOptions
|
||||||
@ -298,6 +299,29 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async loadBurn ({ id, blockNumber, ...values }:DeepPartial<Burn>): Promise<Burn> {
|
||||||
|
return this._conn.transaction(async (tx) => {
|
||||||
|
const repo = tx.getRepository(Burn);
|
||||||
|
|
||||||
|
let selectQueryBuilder = repo.createQueryBuilder('burn')
|
||||||
|
.where('id = :id', { id });
|
||||||
|
|
||||||
|
if (blockNumber) {
|
||||||
|
selectQueryBuilder = selectQueryBuilder.andWhere('block_number <= :blockNumber', { blockNumber });
|
||||||
|
}
|
||||||
|
|
||||||
|
let entity = await selectQueryBuilder.orderBy('block_number', 'DESC')
|
||||||
|
.getOne();
|
||||||
|
|
||||||
|
if (!entity) {
|
||||||
|
entity = repo.create({ blockNumber, id, ...values });
|
||||||
|
entity = await repo.save(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async loadTick ({ id, blockNumber, ...values }: DeepPartial<Tick>): Promise<Tick> {
|
async loadTick ({ id, blockNumber, ...values }: DeepPartial<Tick>): Promise<Tick> {
|
||||||
return this._conn.transaction(async (tx) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Tick);
|
const repo = tx.getRepository(Tick);
|
||||||
@ -470,6 +494,14 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async saveTick (tick: Tick, blockNumber: number): Promise<Tick> {
|
||||||
|
return this._conn.transaction(async (tx) => {
|
||||||
|
const repo = tx.getRepository(Tick);
|
||||||
|
tick.blockNumber = blockNumber;
|
||||||
|
return repo.save(tick);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if events have already been synced for the (block, token) combination.
|
// Returns true if events have already been synced for the (block, token) combination.
|
||||||
async didSyncEvents ({ blockHash, token }: { blockHash: string, token: string }): Promise<boolean> {
|
async didSyncEvents ({ blockHash, token }: { blockHash: string, token: string }): Promise<boolean> {
|
||||||
const numRows = await this._conn.getRepository(EventSyncProgress)
|
const numRows = await this._conn.getRepository(EventSyncProgress)
|
||||||
|
56
packages/uni-info-watcher/src/entity/Burn.ts
Normal file
56
packages/uni-info-watcher/src/entity/Burn.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
|
||||||
|
import Decimal from 'decimal.js';
|
||||||
|
import { decimalTransformer } from '@vulcanize/util';
|
||||||
|
|
||||||
|
import { Transaction } from './Transaction';
|
||||||
|
import { Pool } from './Pool';
|
||||||
|
import { Token } from './Token';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Burn {
|
||||||
|
@PrimaryColumn('varchar')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@PrimaryColumn('integer')
|
||||||
|
blockNumber!: number;
|
||||||
|
|
||||||
|
@ManyToOne(() => Transaction, transaction => transaction.mints)
|
||||||
|
transaction!: Transaction
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
timestamp!: BigInt;
|
||||||
|
|
||||||
|
@ManyToOne(() => Pool)
|
||||||
|
pool!: Pool
|
||||||
|
|
||||||
|
@ManyToOne(() => Token)
|
||||||
|
token0!: Token
|
||||||
|
|
||||||
|
@ManyToOne(() => Token)
|
||||||
|
token1!: Token
|
||||||
|
|
||||||
|
@Column('varchar', { length: 42 })
|
||||||
|
owner!: string
|
||||||
|
|
||||||
|
// TODO: Assign origin with Transaction from address.
|
||||||
|
// @Column('varchar', { length: 42 })
|
||||||
|
// origin!: string
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
amount!: bigint
|
||||||
|
|
||||||
|
@Column('numeric', { transformer: decimalTransformer })
|
||||||
|
amount0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { transformer: decimalTransformer })
|
||||||
|
amount1!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { transformer: decimalTransformer })
|
||||||
|
amountUSD!: Decimal
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
tickLower!: bigint
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
tickUpper!: bigint
|
||||||
|
}
|
@ -36,6 +36,15 @@ interface MintEvent {
|
|||||||
amount1: bigint;
|
amount1: bigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BurnEvent {
|
||||||
|
owner: string;
|
||||||
|
tickLower: bigint;
|
||||||
|
tickUpper: bigint;
|
||||||
|
amount: bigint;
|
||||||
|
amount0: bigint;
|
||||||
|
amount1: bigint;
|
||||||
|
}
|
||||||
|
|
||||||
interface ResultEvent {
|
interface ResultEvent {
|
||||||
proof: {
|
proof: {
|
||||||
data: string
|
data: string
|
||||||
@ -93,6 +102,11 @@ export class EventWatcher {
|
|||||||
this._handleMint(blockHash, blockNumber, contract, txHash, eventValues as MintEvent);
|
this._handleMint(blockHash, blockNumber, contract, txHash, eventValues as MintEvent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'BurnEvent':
|
||||||
|
log('Pool Burn event', contract);
|
||||||
|
this._handleBurn(blockHash, blockNumber, contract, txHash, eventValues as BurnEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -324,6 +338,130 @@ export class EventWatcher {
|
|||||||
await this._db.savePool(pool, blockNumber);
|
await this._db.savePool(pool, blockNumber);
|
||||||
await this._db.saveFactory(factory, blockNumber);
|
await this._db.saveFactory(factory, blockNumber);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
await this._db.saveTick(lowerTick, blockNumber),
|
||||||
|
await this._db.saveTick(upperTick, blockNumber)
|
||||||
|
]);
|
||||||
|
|
||||||
// Skipping update inner tick vars and tick day data as they are not queried.
|
// Skipping update inner tick vars and tick day data as they are not queried.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _handleBurn (blockHash: string, blockNumber: number, contractAddress: string, txHash: string, burnEvent: BurnEvent): Promise<void> {
|
||||||
|
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
||||||
|
const poolAddress = contractAddress;
|
||||||
|
const pool = await this._db.loadPool({ id: poolAddress, blockNumber });
|
||||||
|
|
||||||
|
// 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.getFactories({ blockNumber }, { limit: 1 });
|
||||||
|
|
||||||
|
const token0 = pool.token0;
|
||||||
|
const token1 = pool.token1;
|
||||||
|
const amount0 = convertTokenToDecimal(burnEvent.amount0, token0.decimals);
|
||||||
|
const amount1 = convertTokenToDecimal(burnEvent.amount1, token1.decimals);
|
||||||
|
|
||||||
|
const amountUSD = amount0
|
||||||
|
.times(token0.derivedETH.times(bundle.ethPriceUSD))
|
||||||
|
.plus(amount1.times(token1.derivedETH.times(bundle.ethPriceUSD)));
|
||||||
|
|
||||||
|
// Reset tvl aggregates until new amounts calculated.
|
||||||
|
factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH);
|
||||||
|
|
||||||
|
// Update globals.
|
||||||
|
factory.txCount = factory.txCount + BigInt(1);
|
||||||
|
|
||||||
|
// Update token0 data.
|
||||||
|
token0.txCount = token0.txCount + BigInt(1);
|
||||||
|
token0.totalValueLocked = token0.totalValueLocked.minus(amount0);
|
||||||
|
token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD));
|
||||||
|
|
||||||
|
// Update token1 data.
|
||||||
|
token1.txCount = token1.txCount + BigInt(1);
|
||||||
|
token1.totalValueLocked = token1.totalValueLocked.minus(amount1);
|
||||||
|
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD));
|
||||||
|
|
||||||
|
// Pool data.
|
||||||
|
pool.txCount = pool.txCount + BigInt(1);
|
||||||
|
|
||||||
|
// Pools liquidity tracks the currently active liquidity given pools current tick.
|
||||||
|
// We only want to update it on burn if the position being burnt includes the current tick.
|
||||||
|
if (
|
||||||
|
pool.tick !== null &&
|
||||||
|
burnEvent.tickLower <= pool.tick &&
|
||||||
|
burnEvent.tickUpper > pool.tick
|
||||||
|
) {
|
||||||
|
pool.liquidity = pool.liquidity - burnEvent.amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
pool.totalValueLockedToken0 = pool.totalValueLockedToken0.minus(amount0);
|
||||||
|
pool.totalValueLockedToken1 = pool.totalValueLockedToken1.minus(amount1);
|
||||||
|
|
||||||
|
pool.totalValueLockedETH = pool.totalValueLockedToken0
|
||||||
|
.times(token0.derivedETH)
|
||||||
|
.plus(pool.totalValueLockedToken1.times(token1.derivedETH));
|
||||||
|
|
||||||
|
pool.totalValueLockedUSD = pool.totalValueLockedETH.times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
|
// Reset aggregates with new amounts.
|
||||||
|
factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH);
|
||||||
|
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
|
// Burn entity.
|
||||||
|
const transaction = await loadTransaction(this._db, { txHash, blockNumber });
|
||||||
|
|
||||||
|
await this._db.loadBurn({
|
||||||
|
id: transaction.id + '#' + pool.txCount.toString(),
|
||||||
|
blockNumber,
|
||||||
|
transaction,
|
||||||
|
timestamp: transaction.timestamp,
|
||||||
|
pool,
|
||||||
|
token0: pool.token0,
|
||||||
|
token1: pool.token1,
|
||||||
|
owner: burnEvent.owner,
|
||||||
|
|
||||||
|
// TODO: Assign origin with Transaction from address.
|
||||||
|
// origin: event.transaction.from
|
||||||
|
|
||||||
|
amount: burnEvent.amount,
|
||||||
|
amount0,
|
||||||
|
amount1,
|
||||||
|
amountUSD,
|
||||||
|
tickLower: burnEvent.tickLower,
|
||||||
|
tickUpper: burnEvent.tickUpper
|
||||||
|
});
|
||||||
|
|
||||||
|
// Tick entities.
|
||||||
|
const lowerTickId = poolAddress + '#' + (burnEvent.tickLower).toString();
|
||||||
|
const upperTickId = poolAddress + '#' + (burnEvent.tickUpper).toString();
|
||||||
|
const lowerTick = await this._db.loadTick({ id: lowerTickId, blockNumber });
|
||||||
|
const upperTick = await this._db.loadTick({ id: upperTickId, blockNumber });
|
||||||
|
const amount = burnEvent.amount;
|
||||||
|
lowerTick.liquidityGross = lowerTick.liquidityGross - amount;
|
||||||
|
lowerTick.liquidityNet = lowerTick.liquidityNet - amount;
|
||||||
|
upperTick.liquidityGross = upperTick.liquidityGross - amount;
|
||||||
|
upperTick.liquidityNet = upperTick.liquidityNet + amount;
|
||||||
|
|
||||||
|
await updateUniswapDayData(this._db, { blockNumber, contractAddress });
|
||||||
|
await updatePoolDayData(this._db, { blockNumber, contractAddress });
|
||||||
|
await updatePoolHourData(this._db, { blockNumber, contractAddress });
|
||||||
|
await updateTokenDayData(this._db, token0, { blockNumber });
|
||||||
|
await updateTokenDayData(this._db, token0, { blockNumber });
|
||||||
|
await updateTokenHourData(this._db, token0, { blockNumber });
|
||||||
|
await updateTokenHourData(this._db, token0, { blockNumber });
|
||||||
|
|
||||||
|
// Skipping update Tick fee and Tick day data as they are not queried.
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
await this._db.saveTick(lowerTick, blockNumber),
|
||||||
|
await this._db.saveTick(upperTick, blockNumber)
|
||||||
|
]);
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
this._db.saveToken(token0, blockNumber),
|
||||||
|
this._db.saveToken(token1, blockNumber)
|
||||||
|
]);
|
||||||
|
|
||||||
|
await this._db.savePool(pool, blockNumber);
|
||||||
|
await this._db.saveFactory(factory, blockNumber);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,15 @@ export class Client {
|
|||||||
amount0
|
amount0
|
||||||
amount1
|
amount1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
... on BurnEvent {
|
||||||
|
owner
|
||||||
|
tickLower
|
||||||
|
tickUpper
|
||||||
|
amount
|
||||||
|
amount0
|
||||||
|
amount1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user