2021-07-02 10:56:32 +00:00
|
|
|
import assert from 'assert';
|
|
|
|
import debug from 'debug';
|
2021-07-06 11:25:11 +00:00
|
|
|
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
|
|
|
import { Client as ERC20Client } from '@vulcanize/erc20-watcher';
|
2021-07-07 05:40:10 +00:00
|
|
|
import { BigNumber } from 'ethers';
|
2021-07-02 10:56:32 +00:00
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
import { Database } from './database';
|
2021-07-09 07:08:25 +00:00
|
|
|
import { findEthPerToken, getEthPriceInUSD, WHITELIST_TOKENS } from './utils/pricing';
|
2021-07-13 06:31:54 +00:00
|
|
|
import { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates';
|
2021-07-09 07:08:25 +00:00
|
|
|
import { Token } from './entity/Token';
|
2021-07-13 06:31:54 +00:00
|
|
|
import { convertTokenToDecimal, loadTransaction } from './utils';
|
|
|
|
import { loadTick } from './utils/tick';
|
2021-07-02 10:56:32 +00:00
|
|
|
|
|
|
|
const log = debug('vulcanize:events');
|
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
interface PoolCreatedEvent {
|
|
|
|
token0: string;
|
|
|
|
token1: string;
|
|
|
|
fee: bigint;
|
|
|
|
tickSpacing: bigint;
|
|
|
|
pool: string;
|
|
|
|
}
|
|
|
|
|
2021-07-09 07:08:25 +00:00
|
|
|
interface InitializeEvent {
|
|
|
|
sqrtPriceX96: bigint;
|
|
|
|
tick: bigint;
|
|
|
|
}
|
|
|
|
|
2021-07-13 06:31:54 +00:00
|
|
|
interface MintEvent {
|
|
|
|
sender: string;
|
|
|
|
owner: string;
|
|
|
|
tickLower: bigint;
|
|
|
|
tickUpper: bigint;
|
|
|
|
amount: bigint;
|
|
|
|
amount0: bigint;
|
|
|
|
amount1: bigint;
|
|
|
|
}
|
|
|
|
|
2021-07-13 07:06:10 +00:00
|
|
|
interface BurnEvent {
|
|
|
|
owner: string;
|
|
|
|
tickLower: bigint;
|
|
|
|
tickUpper: bigint;
|
|
|
|
amount: bigint;
|
|
|
|
amount0: bigint;
|
|
|
|
amount1: bigint;
|
|
|
|
}
|
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
interface ResultEvent {
|
|
|
|
proof: {
|
|
|
|
data: string
|
|
|
|
}
|
|
|
|
event: {
|
|
|
|
__typename: string;
|
|
|
|
[key: string]: any;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-02 10:56:32 +00:00
|
|
|
export class EventWatcher {
|
2021-07-06 11:25:11 +00:00
|
|
|
_db: Database
|
|
|
|
_subscription?: ZenObservable.Subscription
|
|
|
|
_uniClient: UniClient
|
|
|
|
_erc20Client: ERC20Client
|
2021-07-02 10:56:32 +00:00
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
constructor (db: Database, uniClient: UniClient, erc20Client: ERC20Client) {
|
|
|
|
assert(db);
|
2021-07-02 10:56:32 +00:00
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
this._db = db;
|
|
|
|
this._uniClient = uniClient;
|
|
|
|
this._erc20Client = erc20Client;
|
2021-07-02 10:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async start (): Promise<void> {
|
|
|
|
assert(!this._subscription, 'subscription already started');
|
2021-07-06 11:25:11 +00:00
|
|
|
log('Started watching upstream events...');
|
|
|
|
this._subscription = await this._uniClient.watchEvents(this._handleEvents.bind(this));
|
2021-07-02 10:56:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
async stop (): Promise<void> {
|
|
|
|
if (this._subscription) {
|
2021-07-06 11:25:11 +00:00
|
|
|
log('Stopped watching upstream events');
|
2021-07-02 10:56:32 +00:00
|
|
|
this._subscription.unsubscribe();
|
|
|
|
}
|
|
|
|
}
|
2021-07-06 11:25:11 +00:00
|
|
|
|
2021-07-13 06:31:54 +00:00
|
|
|
async _handleEvents ({ blockHash, blockNumber, contract, txHash, event }: { blockHash: string, blockNumber: number, contract: string, txHash: string, event: ResultEvent}): Promise<void> {
|
2021-07-06 11:25:11 +00:00
|
|
|
// TODO: Process proof (proof.data) in event.
|
|
|
|
const { event: { __typename: eventType, ...eventValues } } = event;
|
|
|
|
|
|
|
|
switch (eventType) {
|
|
|
|
case 'PoolCreatedEvent':
|
2021-07-09 07:08:25 +00:00
|
|
|
log('Factory PoolCreated event', contract);
|
2021-07-13 06:31:54 +00:00
|
|
|
this._handlePoolCreated(blockHash, blockNumber, contract, txHash, eventValues as PoolCreatedEvent);
|
2021-07-06 11:25:11 +00:00
|
|
|
break;
|
|
|
|
|
2021-07-09 07:08:25 +00:00
|
|
|
case 'InitializeEvent':
|
|
|
|
log('Pool Initialize event', contract);
|
2021-07-13 06:31:54 +00:00
|
|
|
this._handleInitialize(blockHash, blockNumber, contract, txHash, eventValues as InitializeEvent);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'MintEvent':
|
|
|
|
log('Pool Mint event', contract);
|
|
|
|
this._handleMint(blockHash, blockNumber, contract, txHash, eventValues as MintEvent);
|
2021-07-09 07:08:25 +00:00
|
|
|
break;
|
|
|
|
|
2021-07-13 07:06:10 +00:00
|
|
|
case 'BurnEvent':
|
|
|
|
log('Pool Burn event', contract);
|
|
|
|
this._handleBurn(blockHash, blockNumber, contract, txHash, eventValues as BurnEvent);
|
|
|
|
break;
|
|
|
|
|
2021-07-06 11:25:11 +00:00
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-13 06:31:54 +00:00
|
|
|
async _handlePoolCreated (blockHash: string, blockNumber: number, contractAddress: string, txHash: string, poolCreatedEvent: PoolCreatedEvent): Promise<void> {
|
2021-07-07 05:40:10 +00:00
|
|
|
const { token0: token0Address, token1: token1Address, fee, pool: poolAddress } = poolCreatedEvent;
|
2021-07-06 11:25:11 +00:00
|
|
|
|
|
|
|
// Load factory.
|
|
|
|
const factory = await this._db.loadFactory({ blockNumber, id: contractAddress });
|
|
|
|
|
2021-07-07 05:40:10 +00:00
|
|
|
// Update Factory.
|
|
|
|
let factoryPoolCount = BigNumber.from(factory.poolCount);
|
|
|
|
factoryPoolCount = factoryPoolCount.add(1);
|
|
|
|
factory.poolCount = BigInt(factoryPoolCount.toHexString());
|
|
|
|
|
|
|
|
// Get Tokens.
|
|
|
|
let [token0, token1] = await Promise.all([
|
|
|
|
this._db.getToken({ blockNumber, id: token0Address }),
|
|
|
|
this._db.getToken({ blockNumber, id: token1Address })
|
|
|
|
]);
|
2021-07-06 11:25:11 +00:00
|
|
|
|
2021-07-07 05:40:10 +00:00
|
|
|
// Create Tokens if not present.
|
|
|
|
if (!token0) {
|
2021-07-09 07:08:25 +00:00
|
|
|
token0 = await this._createToken(blockHash, blockNumber, token0Address);
|
2021-07-07 05:40:10 +00:00
|
|
|
}
|
2021-07-06 11:25:11 +00:00
|
|
|
|
2021-07-07 05:40:10 +00:00
|
|
|
if (!token1) {
|
2021-07-09 07:08:25 +00:00
|
|
|
token1 = await this._createToken(blockHash, blockNumber, token1Address);
|
2021-07-07 05:40:10 +00:00
|
|
|
}
|
2021-07-06 11:25:11 +00:00
|
|
|
|
2021-07-07 05:40:10 +00:00
|
|
|
// Create new Pool entity.
|
|
|
|
// Skipping adding createdAtTimestamp field as it is not queried in frontend subgraph.
|
2021-07-09 07:08:25 +00:00
|
|
|
const pool = await this._db.loadPool({
|
2021-07-07 05:40:10 +00:00
|
|
|
blockNumber,
|
|
|
|
id: poolAddress,
|
|
|
|
token0: token0,
|
|
|
|
token1: token1,
|
|
|
|
feeTier: BigInt(fee)
|
|
|
|
});
|
|
|
|
|
2021-07-09 07:08:25 +00:00
|
|
|
// Update white listed pools.
|
|
|
|
if (WHITELIST_TOKENS.includes(token0.id)) {
|
|
|
|
token1.whitelistPools.push(pool);
|
|
|
|
await this._db.saveToken(token1, blockNumber);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (WHITELIST_TOKENS.includes(token1.id)) {
|
|
|
|
token0.whitelistPools.push(pool);
|
|
|
|
await this._db.saveToken(token0, blockNumber);
|
|
|
|
}
|
2021-07-07 05:40:10 +00:00
|
|
|
|
|
|
|
// Save entities to DB.
|
|
|
|
await this._db.saveFactory(factory, blockNumber);
|
2021-07-06 11:25:11 +00:00
|
|
|
}
|
2021-07-09 07:08:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Create new Token.
|
|
|
|
* @param tokenAddress
|
|
|
|
*/
|
|
|
|
async _createToken (blockHash: string, blockNumber: number, tokenAddress: string): Promise<Token> {
|
|
|
|
const { value: symbol } = await this._erc20Client.getSymbol(blockHash, tokenAddress);
|
|
|
|
const { value: name } = await this._erc20Client.getName(blockHash, tokenAddress);
|
|
|
|
const { value: totalSupply } = await this._erc20Client.getTotalSupply(blockHash, tokenAddress);
|
|
|
|
|
|
|
|
// TODO: Decimals not implemented by erc20-watcher.
|
|
|
|
// const { value: decimals } = await this._erc20Client.getDecimals(blockHash, tokenAddress);
|
|
|
|
|
|
|
|
return this._db.loadToken({
|
|
|
|
blockNumber,
|
|
|
|
id: tokenAddress,
|
|
|
|
symbol,
|
|
|
|
name,
|
|
|
|
totalSupply
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-13 06:31:54 +00:00
|
|
|
async _handleInitialize (blockHash: string, blockNumber: number, contractAddress: string, txHash: string, initializeEvent: InitializeEvent): Promise<void> {
|
2021-07-09 07:08:25 +00:00
|
|
|
const { sqrtPriceX96, tick } = initializeEvent;
|
|
|
|
const pool = await this._db.getPool({ id: contractAddress, blockNumber });
|
|
|
|
assert(pool, `Pool ${contractAddress} not found.`);
|
|
|
|
|
|
|
|
// Update Pool.
|
|
|
|
pool.sqrtPrice = BigInt(sqrtPriceX96);
|
|
|
|
pool.tick = BigInt(tick);
|
|
|
|
this._db.savePool(pool, blockNumber);
|
|
|
|
|
|
|
|
// Update ETH price now that prices could have changed.
|
|
|
|
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
|
|
|
bundle.ethPriceUSD = await getEthPriceInUSD(this._db);
|
|
|
|
this._db.saveBundle(bundle, blockNumber);
|
|
|
|
|
|
|
|
await updatePoolDayData(this._db, { contractAddress, blockNumber });
|
|
|
|
await updatePoolHourData(this._db, { contractAddress, blockNumber });
|
|
|
|
|
|
|
|
const [token0, token1] = await Promise.all([
|
|
|
|
this._db.getToken({ id: pool.token0.id, blockNumber }),
|
|
|
|
this._db.getToken({ id: pool.token1.id, blockNumber })
|
|
|
|
]);
|
|
|
|
|
|
|
|
assert(token0 && token1, 'Pool tokens not found.');
|
|
|
|
|
|
|
|
// Update token prices.
|
|
|
|
token0.derivedETH = await findEthPerToken(token0);
|
|
|
|
token1.derivedETH = await findEthPerToken(token1);
|
|
|
|
|
|
|
|
await Promise.all([
|
|
|
|
this._db.saveToken(token0, blockNumber),
|
|
|
|
this._db.saveToken(token1, blockNumber)
|
|
|
|
]);
|
|
|
|
}
|
2021-07-13 06:31:54 +00:00
|
|
|
|
|
|
|
async _handleMint (blockHash: string, blockNumber: number, contractAddress: string, txHash: string, mintEvent: MintEvent): 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(mintEvent.amount0, BigInt(token0.decimals));
|
|
|
|
const amount1 = convertTokenToDecimal(mintEvent.amount1, BigInt(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 = BigInt(factory.txCount) + BigInt(1);
|
|
|
|
|
|
|
|
// Update token0 data.
|
|
|
|
token0.txCount = BigInt(token0.txCount) + BigInt(1);
|
|
|
|
token0.totalValueLocked = token0.totalValueLocked.plus(amount0);
|
|
|
|
token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD));
|
|
|
|
|
|
|
|
// Update token1 data.
|
|
|
|
token1.txCount = BigInt(token1.txCount) + BigInt(1);
|
|
|
|
token1.totalValueLocked = token1.totalValueLocked.plus(amount1);
|
|
|
|
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD));
|
|
|
|
|
|
|
|
// Pool data.
|
|
|
|
pool.txCount = BigInt(pool.txCount) + BigInt(1);
|
|
|
|
|
|
|
|
// Pools liquidity tracks the currently active liquidity given pools current tick.
|
|
|
|
// We only want to update it on mint if the new position includes the current tick.
|
|
|
|
if (pool.tick !== null) {
|
|
|
|
if (
|
|
|
|
BigInt(mintEvent.tickLower) <= BigInt(pool.tick) &&
|
|
|
|
BigInt(mintEvent.tickUpper) > BigInt(pool.tick)
|
|
|
|
) {
|
|
|
|
pool.liquidity = BigInt(pool.liquidity) + mintEvent.amount;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pool.totalValueLockedToken0 = pool.totalValueLockedToken0.plus(amount0);
|
|
|
|
pool.totalValueLockedToken1 = pool.totalValueLockedToken1.plus(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);
|
|
|
|
|
|
|
|
const transaction = await loadTransaction(this._db, { txHash, blockNumber });
|
|
|
|
|
|
|
|
await this._db.loadMint({
|
|
|
|
id: transaction.id + '#' + pool.txCount.toString(),
|
|
|
|
blockNumber,
|
|
|
|
transaction,
|
|
|
|
timestamp: transaction.timestamp,
|
|
|
|
pool,
|
|
|
|
token0: pool.token0,
|
|
|
|
token1: pool.token1,
|
|
|
|
owner: mintEvent.owner,
|
|
|
|
sender: mintEvent.sender,
|
|
|
|
|
|
|
|
// TODO: Assign origin with Transaction from address.
|
|
|
|
// origin: event.transaction.from
|
|
|
|
|
|
|
|
amount: mintEvent.amount,
|
|
|
|
amount0: amount0,
|
|
|
|
amount1: amount1,
|
|
|
|
amountUSD: amountUSD,
|
|
|
|
tickLower: mintEvent.tickLower,
|
|
|
|
tickUpper: mintEvent.tickUpper
|
|
|
|
});
|
|
|
|
|
|
|
|
// Tick entities.
|
|
|
|
const lowerTickIdx = mintEvent.tickLower;
|
|
|
|
const upperTickIdx = mintEvent.tickUpper;
|
|
|
|
|
|
|
|
const lowerTickId = poolAddress + '#' + mintEvent.tickLower.toString();
|
|
|
|
const upperTickId = poolAddress + '#' + mintEvent.tickUpper.toString();
|
|
|
|
|
|
|
|
const lowerTick = await loadTick(this._db, lowerTickId, lowerTickIdx, pool, blockNumber);
|
|
|
|
const upperTick = await loadTick(this._db, upperTickId, upperTickIdx, pool, blockNumber);
|
|
|
|
|
|
|
|
const amount = mintEvent.amount;
|
|
|
|
lowerTick.liquidityGross = lowerTick.liquidityGross + amount;
|
|
|
|
lowerTick.liquidityNet = lowerTick.liquidityNet + amount;
|
|
|
|
upperTick.liquidityGross = upperTick.liquidityGross + amount;
|
|
|
|
upperTick.liquidityNet = upperTick.liquidityNet + amount;
|
|
|
|
|
|
|
|
// TODO: Update Tick's volume, fees, and liquidity provider count.
|
|
|
|
// Computing these on the tick level requires reimplementing some of the swapping code from v3-core.
|
|
|
|
|
|
|
|
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, token1, { blockNumber });
|
|
|
|
await updateTokenHourData(this._db, token0, { blockNumber });
|
|
|
|
await updateTokenHourData(this._db, token1, { 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);
|
|
|
|
|
2021-07-13 07:06:10 +00:00
|
|
|
await Promise.all([
|
|
|
|
await this._db.saveTick(lowerTick, blockNumber),
|
|
|
|
await this._db.saveTick(upperTick, blockNumber)
|
|
|
|
]);
|
|
|
|
|
2021-07-13 06:31:54 +00:00
|
|
|
// Skipping update inner tick vars and tick day data as they are not queried.
|
|
|
|
}
|
2021-07-13 07:06:10 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2021-07-02 10:56:32 +00:00
|
|
|
}
|