mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-08 12:28:05 +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 { TokenDayData } from './entity/TokenDayData';
|
||||
import { TokenHourData } from './entity/TokenHourData';
|
||||
import { Burn } from './entity/Burn';
|
||||
|
||||
export class Database {
|
||||
_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> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
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.
|
||||
async didSyncEvents ({ blockHash, token }: { blockHash: string, token: string }): Promise<boolean> {
|
||||
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;
|
||||
}
|
||||
|
||||
interface BurnEvent {
|
||||
owner: string;
|
||||
tickLower: bigint;
|
||||
tickUpper: bigint;
|
||||
amount: bigint;
|
||||
amount0: bigint;
|
||||
amount1: bigint;
|
||||
}
|
||||
|
||||
interface ResultEvent {
|
||||
proof: {
|
||||
data: string
|
||||
@ -93,6 +102,11 @@ export class EventWatcher {
|
||||
this._handleMint(blockHash, blockNumber, contract, txHash, eventValues as MintEvent);
|
||||
break;
|
||||
|
||||
case 'BurnEvent':
|
||||
log('Pool Burn event', contract);
|
||||
this._handleBurn(blockHash, blockNumber, contract, txHash, eventValues as BurnEvent);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -324,6 +338,130 @@ export class EventWatcher {
|
||||
await this._db.savePool(pool, 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.
|
||||
}
|
||||
|
||||
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
|
||||
amount1
|
||||
}
|
||||
|
||||
... on BurnEvent {
|
||||
owner
|
||||
tickLower
|
||||
tickUpper
|
||||
amount
|
||||
amount0
|
||||
amount1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user