mirror of
https://github.com/cerc-io/watcher-ts
synced 2024-11-19 12:26:19 +00:00
Add block hash to entities, split get and set methods (#161)
* Split get and set entity for PoolCreated and Initialize events. * Split get/set entity for Mint, Burn and Swap events. * Split get/set entity for IncreaseLiquidity and DecreaseLiquidity events. * Split get/set for NFPM Transfer and Collect events. * Add blockHash to entities. Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
parent
26965f372f
commit
f8335aad03
@ -45,6 +45,44 @@ export class Database {
|
||||
return this._conn.close();
|
||||
}
|
||||
|
||||
async getFactory ({ id, blockNumber }: DeepPartial<Factory>): Promise<Factory | undefined> {
|
||||
const repo = this._conn.getRepository(Factory);
|
||||
|
||||
const whereOptions: FindConditions<Factory> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<Factory> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getBundle ({ id, blockNumber }: DeepPartial<Bundle>): Promise<Bundle | undefined> {
|
||||
const repo = this._conn.getRepository(Bundle);
|
||||
|
||||
const whereOptions: FindConditions<Bundle> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<Bundle> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getToken ({ id, blockNumber }: DeepPartial<Token>): Promise<Token | undefined> {
|
||||
const repo = this._conn.getRepository(Token);
|
||||
|
||||
@ -122,6 +160,114 @@ export class Database {
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getPoolDayData ({ id, blockNumber }: DeepPartial<PoolDayData>): Promise<PoolDayData | undefined> {
|
||||
const repo = this._conn.getRepository(PoolDayData);
|
||||
const whereOptions: FindConditions<PoolDayData> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<PoolDayData> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getPoolHourData ({ id, blockNumber }: DeepPartial<PoolHourData>): Promise<PoolHourData | undefined> {
|
||||
const repo = this._conn.getRepository(PoolHourData);
|
||||
const whereOptions: FindConditions<PoolHourData> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<PoolHourData> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getUniswapDayData ({ id, blockNumber }: DeepPartial<UniswapDayData>): Promise<UniswapDayData | undefined> {
|
||||
const repo = this._conn.getRepository(UniswapDayData);
|
||||
const whereOptions: FindConditions<UniswapDayData> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<UniswapDayData> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getTokenDayData ({ id, blockNumber }: DeepPartial<TokenDayData>): Promise<TokenDayData | undefined> {
|
||||
const repo = this._conn.getRepository(TokenDayData);
|
||||
const whereOptions: FindConditions<TokenDayData> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<TokenDayData> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getTokenHourData ({ id, blockNumber }: DeepPartial<TokenHourData>): Promise<TokenHourData | undefined> {
|
||||
const repo = this._conn.getRepository(TokenHourData);
|
||||
const whereOptions: FindConditions<TokenHourData> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<TokenHourData> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getTransaction ({ id, blockNumber }: DeepPartial<Transaction>): Promise<Transaction | undefined> {
|
||||
const repo = this._conn.getRepository(Transaction);
|
||||
const whereOptions: FindConditions<Transaction> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<Transaction> = {
|
||||
where: whereOptions,
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
return repo.findOne(findOptions);
|
||||
}
|
||||
|
||||
async getFactories ({ blockNumber }: DeepPartial<Factory>, queryOptions: { [key: string]: any }): Promise<Array<Factory>> {
|
||||
const repo = this._conn.getRepository(Factory);
|
||||
|
||||
@ -143,485 +289,150 @@ export class Database {
|
||||
return selectQueryBuilder.getMany();
|
||||
}
|
||||
|
||||
async loadFactory ({ id, blockNumber, ...values }: DeepPartial<Factory>): Promise<Factory> {
|
||||
async saveFactory (factory: Factory, block: Block): Promise<Factory> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Factory);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('factory')
|
||||
.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 loadPool ({ id, blockNumber, ...values }: DeepPartial<Pool>): Promise<Pool> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Pool);
|
||||
|
||||
const whereOptions: FindConditions<Pool> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<Pool> = {
|
||||
where: whereOptions,
|
||||
relations: ['token0', 'token1'],
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
let entity = await repo.findOne(findOptions);
|
||||
|
||||
if (!entity) {
|
||||
entity = repo.create({ blockNumber, id, ...values });
|
||||
entity = await repo.save(entity);
|
||||
}
|
||||
|
||||
return entity;
|
||||
});
|
||||
}
|
||||
|
||||
async loadToken ({ id, blockNumber, ...values }: DeepPartial<Token>): Promise<Token> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Token);
|
||||
|
||||
const whereOptions: FindConditions<Token> = { id };
|
||||
|
||||
if (blockNumber) {
|
||||
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||
}
|
||||
|
||||
const findOptions: FindOneOptions<Token> = {
|
||||
where: whereOptions,
|
||||
relations: ['whitelistPools', 'whitelistPools.token0', 'whitelistPools.token1'],
|
||||
order: {
|
||||
blockNumber: 'DESC'
|
||||
}
|
||||
};
|
||||
|
||||
let entity = await repo.findOne(findOptions);
|
||||
|
||||
if (!entity) {
|
||||
entity = repo.create({ blockNumber, id, ...values });
|
||||
entity = await repo.save(entity);
|
||||
|
||||
// TODO: Find way to preload relations during create.
|
||||
entity.whitelistPools = [];
|
||||
}
|
||||
|
||||
return entity;
|
||||
});
|
||||
}
|
||||
|
||||
async loadBundle ({ id, blockNumber, ...values }: DeepPartial<Bundle>): Promise<Bundle> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Bundle);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('bundle')
|
||||
.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 loadPoolDayData ({ id, blockNumber, ...values }: DeepPartial<PoolDayData>): Promise<PoolDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PoolDayData);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('pool_day_data')
|
||||
.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 loadPoolHourData ({ id, blockNumber, ...values }: DeepPartial<PoolHourData>): Promise<PoolHourData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PoolHourData);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('pool_hour_data')
|
||||
.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 loadTransaction ({ id, blockNumber, ...values }: DeepPartial<Transaction>): Promise<Transaction> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Transaction);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('transaction')
|
||||
.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 loadMint ({ id, blockNumber, ...values }:DeepPartial<Mint>): Promise<Mint> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Mint);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('mint')
|
||||
.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 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 loadSwap ({ id, blockNumber, ...values }:DeepPartial<Swap>): Promise<Swap> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Swap);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('swap')
|
||||
.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);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('tick')
|
||||
.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 loadUniswapDayData ({ id, blockNumber, ...values }: DeepPartial<UniswapDayData>): Promise<UniswapDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(UniswapDayData);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('uniswap_day_data')
|
||||
.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 loadTokenDayData ({ id, blockNumber, ...values }: DeepPartial<TokenDayData>): Promise<TokenDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(TokenDayData);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('token_day_data')
|
||||
.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 loadTokenHourData ({ id, blockNumber, ...values }: DeepPartial<TokenHourData>): Promise<TokenHourData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(TokenHourData);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('token_hour_data')
|
||||
.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 loadPosition ({ id, blockNumber, ...values }: DeepPartial<Position>): Promise<Position> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Position);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('position')
|
||||
.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 loadPositionSnapshot ({ id, blockNumber, ...values }: DeepPartial<PositionSnapshot>): Promise<PositionSnapshot> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PositionSnapshot);
|
||||
|
||||
let selectQueryBuilder = repo.createQueryBuilder('positionSnapshot')
|
||||
.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 saveFactory (factory: Factory, blockNumber: number): Promise<Factory> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Factory);
|
||||
factory.blockNumber = blockNumber;
|
||||
factory.blockNumber = block.number;
|
||||
factory.blockHash = block.hash;
|
||||
return repo.save(factory);
|
||||
});
|
||||
}
|
||||
|
||||
async saveBundle (bundle: Bundle, blockNumber: number): Promise<Bundle> {
|
||||
async saveBundle (bundle: Bundle, block: Block): Promise<Bundle> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Bundle);
|
||||
bundle.blockNumber = blockNumber;
|
||||
bundle.blockNumber = block.number;
|
||||
bundle.blockHash = block.hash;
|
||||
return repo.save(bundle);
|
||||
});
|
||||
}
|
||||
|
||||
async savePool (pool: Pool, blockNumber: number): Promise<Pool> {
|
||||
async savePool (pool: Pool, block: Block): Promise<Pool> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Pool);
|
||||
pool.blockNumber = blockNumber;
|
||||
pool.blockNumber = block.number;
|
||||
pool.blockHash = block.hash;
|
||||
return repo.save(pool);
|
||||
});
|
||||
}
|
||||
|
||||
async savePoolDayData (poolDayData: PoolDayData, blockNumber: number): Promise<PoolDayData> {
|
||||
async savePoolDayData (poolDayData: PoolDayData, block: Block): Promise<PoolDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PoolDayData);
|
||||
poolDayData.blockNumber = blockNumber;
|
||||
poolDayData.blockNumber = block.number;
|
||||
poolDayData.blockHash = block.hash;
|
||||
return repo.save(poolDayData);
|
||||
});
|
||||
}
|
||||
|
||||
async savePoolHourData (poolHourData: PoolHourData, blockNumber: number): Promise<PoolHourData> {
|
||||
async savePoolHourData (poolHourData: PoolHourData, block: Block): Promise<PoolHourData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PoolHourData);
|
||||
poolHourData.blockNumber = blockNumber;
|
||||
poolHourData.blockNumber = block.number;
|
||||
poolHourData.blockHash = block.hash;
|
||||
return repo.save(poolHourData);
|
||||
});
|
||||
}
|
||||
|
||||
async saveToken (token: Token, blockNumber: number): Promise<Token> {
|
||||
async saveToken (token: Token, block: Block): Promise<Token> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Token);
|
||||
token.blockNumber = blockNumber;
|
||||
token.blockNumber = block.number;
|
||||
token.blockHash = block.hash;
|
||||
return repo.save(token);
|
||||
});
|
||||
}
|
||||
|
||||
async saveTransaction (transaction: Transaction, blockNumber: number): Promise<Transaction> {
|
||||
async saveTransaction (transaction: Transaction, block: Block): Promise<Transaction> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Transaction);
|
||||
transaction.blockNumber = blockNumber;
|
||||
transaction.blockNumber = block.number;
|
||||
transaction.blockHash = block.hash;
|
||||
return repo.save(transaction);
|
||||
});
|
||||
}
|
||||
|
||||
async saveUniswapDayData (uniswapDayData: UniswapDayData, blockNumber: number): Promise<UniswapDayData> {
|
||||
async saveUniswapDayData (uniswapDayData: UniswapDayData, block: Block): Promise<UniswapDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(UniswapDayData);
|
||||
uniswapDayData.blockNumber = blockNumber;
|
||||
uniswapDayData.blockNumber = block.number;
|
||||
uniswapDayData.blockHash = block.hash;
|
||||
return repo.save(uniswapDayData);
|
||||
});
|
||||
}
|
||||
|
||||
async saveTokenDayData (tokenDayData: TokenDayData, blockNumber: number): Promise<TokenDayData> {
|
||||
async saveTokenDayData (tokenDayData: TokenDayData, block: Block): Promise<TokenDayData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(TokenDayData);
|
||||
tokenDayData.blockNumber = blockNumber;
|
||||
tokenDayData.blockNumber = block.number;
|
||||
tokenDayData.blockHash = block.hash;
|
||||
return repo.save(tokenDayData);
|
||||
});
|
||||
}
|
||||
|
||||
async saveTokenHourData (tokenHourData: TokenHourData, blockNumber: number): Promise<TokenHourData> {
|
||||
async saveTokenHourData (tokenHourData: TokenHourData, block: Block): Promise<TokenHourData> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(TokenHourData);
|
||||
tokenHourData.blockNumber = blockNumber;
|
||||
tokenHourData.blockNumber = block.number;
|
||||
tokenHourData.blockHash = block.hash;
|
||||
return repo.save(tokenHourData);
|
||||
});
|
||||
}
|
||||
|
||||
async saveTick (tick: Tick, blockNumber: number): Promise<Tick> {
|
||||
async saveTick (tick: Tick, block: Block): Promise<Tick> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Tick);
|
||||
tick.blockNumber = blockNumber;
|
||||
tick.blockNumber = block.number;
|
||||
tick.blockHash = block.hash;
|
||||
return repo.save(tick);
|
||||
});
|
||||
}
|
||||
|
||||
async savePosition (position: Position, blockNumber: number): Promise<Position> {
|
||||
async savePosition (position: Position, block: Block): Promise<Position> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Position);
|
||||
position.blockNumber = blockNumber;
|
||||
position.blockNumber = block.number;
|
||||
position.blockHash = block.hash;
|
||||
return repo.save(position);
|
||||
});
|
||||
}
|
||||
|
||||
async savePositionSnapshot (positionSnapshot: PositionSnapshot, block: Block): Promise<PositionSnapshot> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(PositionSnapshot);
|
||||
positionSnapshot.blockNumber = block.number;
|
||||
positionSnapshot.blockHash = block.hash;
|
||||
return repo.save(positionSnapshot);
|
||||
});
|
||||
}
|
||||
|
||||
async saveMint (mint: Mint, block: Block): Promise<Mint> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Mint);
|
||||
mint.blockNumber = block.number;
|
||||
mint.blockHash = block.hash;
|
||||
return repo.save(mint);
|
||||
});
|
||||
}
|
||||
|
||||
async saveBurn (burn: Burn, block: Block): Promise<Burn> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Burn);
|
||||
burn.blockNumber = block.number;
|
||||
burn.blockHash = block.hash;
|
||||
return repo.save(burn);
|
||||
});
|
||||
}
|
||||
|
||||
async saveSwap (swap: Swap, block: Block): Promise<Swap> {
|
||||
return this._conn.transaction(async (tx) => {
|
||||
const repo = tx.getRepository(Swap);
|
||||
swap.blockNumber = block.number;
|
||||
swap.blockHash = block.hash;
|
||||
return repo.save(swap);
|
||||
});
|
||||
}
|
||||
|
||||
// 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)
|
||||
|
@ -7,7 +7,10 @@ export class Bundle {
|
||||
@PrimaryColumn('varchar', { length: 1 })
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||
|
@ -11,7 +11,10 @@ export class Burn {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@ManyToOne(() => Transaction, transaction => transaction.burns)
|
||||
|
@ -7,7 +7,10 @@ export class Factory {
|
||||
@PrimaryColumn('varchar', { length: 42 })
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('bigint', { default: BigInt(0) })
|
||||
|
@ -11,7 +11,10 @@ export class Mint {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@ManyToOne(() => Transaction, transaction => transaction.mints)
|
||||
|
@ -9,7 +9,10 @@ export class Pool {
|
||||
@PrimaryColumn('varchar', { length: 42 })
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@ManyToOne(() => Token)
|
||||
|
@ -9,7 +9,10 @@ export class PoolDayData {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('integer')
|
||||
|
@ -9,7 +9,10 @@ export class PoolHourData {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('integer')
|
||||
|
@ -13,7 +13,10 @@ export class Position {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('bigint')
|
||||
|
@ -12,7 +12,10 @@ export class PositionSnapshot {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('bigint')
|
||||
|
@ -11,7 +11,10 @@ export class Swap {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@ManyToOne(() => Transaction, transaction => transaction.swaps)
|
||||
|
@ -9,7 +9,10 @@ export class Tick {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('bigint')
|
||||
|
@ -9,7 +9,10 @@ export class Token {
|
||||
@PrimaryColumn('varchar', { length: 42 })
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('varchar')
|
||||
|
@ -9,7 +9,10 @@ export class TokenDayData {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('integer')
|
||||
|
@ -9,7 +9,10 @@ export class TokenHourData {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('integer')
|
||||
|
@ -11,7 +11,10 @@ export class Transaction {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||
|
@ -7,7 +7,10 @@ export class UniswapDayData {
|
||||
@PrimaryColumn('varchar')
|
||||
id!: string;
|
||||
|
||||
@PrimaryColumn('integer')
|
||||
@PrimaryColumn('varchar', { length: 66 })
|
||||
blockHash!: string
|
||||
|
||||
@Column('integer')
|
||||
blockNumber!: number;
|
||||
|
||||
@Column('integer')
|
||||
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
||||
import debug from 'debug';
|
||||
import { DeepPartial } from 'typeorm';
|
||||
import JSONbig from 'json-bigint';
|
||||
import { BigNumber, utils } from 'ethers';
|
||||
import { utils } from 'ethers';
|
||||
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
||||
import { Client as ERC20Client } from '@vulcanize/erc20-watcher';
|
||||
|
||||
@ -10,12 +10,19 @@ import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToT
|
||||
import { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates';
|
||||
import { Token } from './entity/Token';
|
||||
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
|
||||
import { loadTick } from './utils/tick';
|
||||
import { createTick } from './utils/tick';
|
||||
import Decimal from 'decimal.js';
|
||||
import { Position } from './entity/Position';
|
||||
import { Database } from './database';
|
||||
import { Event } from './entity/Event';
|
||||
import { ResultEvent, Block, Transaction, PoolCreatedEvent, InitializeEvent, MintEvent, BurnEvent, SwapEvent, IncreaseLiquidityEvent, DecreaseLiquidityEvent, CollectEvent, TransferEvent } from './events';
|
||||
import { Factory } from './entity/Factory';
|
||||
import { Bundle } from './entity/Bundle';
|
||||
import { Pool } from './entity/Pool';
|
||||
import { Mint } from './entity/Mint';
|
||||
import { Burn } from './entity/Burn';
|
||||
import { Swap } from './entity/Swap';
|
||||
import { PositionSnapshot } from './entity/PositionSnapshot';
|
||||
|
||||
const log = debug('vulcanize:indexer');
|
||||
|
||||
@ -88,7 +95,7 @@ export class Indexer {
|
||||
const resultEvent = this.getResultEvent(dbEvent);
|
||||
|
||||
// TODO: Process proof (proof.data) in event.
|
||||
const { contract, block, tx, event } = resultEvent;
|
||||
const { contract, tx, block, event } = resultEvent;
|
||||
const { __typename: eventType } = event;
|
||||
|
||||
switch (eventType) {
|
||||
@ -179,16 +186,33 @@ export class Indexer {
|
||||
}
|
||||
|
||||
async _handlePoolCreated (block: Block, contractAddress: string, tx: Transaction, poolCreatedEvent: PoolCreatedEvent): Promise<void> {
|
||||
const { number: blockNumber, hash: blockHash } = block;
|
||||
const { number: blockNumber } = block;
|
||||
const { token0: token0Address, token1: token1Address, fee, pool: poolAddress } = poolCreatedEvent;
|
||||
|
||||
// Temp fix from Subgraph mapping code.
|
||||
if (utils.getAddress(poolAddress) === utils.getAddress('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load factory.
|
||||
const factory = await this._db.loadFactory({ blockNumber, id: contractAddress });
|
||||
let factory = await this._db.getFactory({ blockNumber, id: contractAddress });
|
||||
|
||||
if (!factory) {
|
||||
factory = new Factory();
|
||||
factory.id = contractAddress;
|
||||
factory = await this._db.saveFactory(factory, block);
|
||||
|
||||
// Create new bundle for tracking eth price.
|
||||
const bundle = new Bundle();
|
||||
bundle.id = '1';
|
||||
await this._db.saveBundle(bundle, block);
|
||||
}
|
||||
|
||||
// Update Factory.
|
||||
let factoryPoolCount = BigNumber.from(factory.poolCount);
|
||||
factoryPoolCount = factoryPoolCount.add(1);
|
||||
factory.poolCount = BigInt(factoryPoolCount.toHexString());
|
||||
factory.poolCount = BigInt(factory.poolCount) + BigInt(1);
|
||||
|
||||
let pool = new Pool();
|
||||
pool.id = poolAddress;
|
||||
|
||||
// Get Tokens.
|
||||
let [token0, token1] = await Promise.all([
|
||||
@ -198,61 +222,59 @@ export class Indexer {
|
||||
|
||||
// Create Tokens if not present.
|
||||
if (!token0) {
|
||||
token0 = await this._createToken(blockHash, blockNumber, token0Address);
|
||||
token0 = await this._createToken(block, token0Address);
|
||||
}
|
||||
|
||||
if (!token1) {
|
||||
token1 = await this._createToken(blockHash, blockNumber, token1Address);
|
||||
token1 = await this._createToken(block, token1Address);
|
||||
}
|
||||
|
||||
// Create new Pool entity.
|
||||
// Skipping adding createdAtTimestamp field as it is not queried in frontend subgraph.
|
||||
const pool = await this._db.loadPool({
|
||||
blockNumber,
|
||||
id: poolAddress,
|
||||
token0: token0,
|
||||
token1: token1,
|
||||
feeTier: BigInt(fee)
|
||||
});
|
||||
pool.token0 = token0;
|
||||
pool.token1 = token1;
|
||||
pool.feeTier = BigInt(fee);
|
||||
pool = await this._db.savePool(pool, block);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Skipping adding createdAtTimestamp field as it is not queried in frontend subgraph.
|
||||
|
||||
// Save entities to DB.
|
||||
await this._db.saveFactory(factory, blockNumber);
|
||||
await this._db.saveToken(token0, block);
|
||||
await this._db.saveToken(token1, block);
|
||||
await this._db.saveFactory(factory, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
async _createToken (block: Block, tokenAddress: string): Promise<Token> {
|
||||
const token = new Token();
|
||||
token.id = tokenAddress;
|
||||
|
||||
const { value: symbol } = await this._erc20Client.getSymbol(block.hash, tokenAddress);
|
||||
const { value: name } = await this._erc20Client.getName(block.hash, tokenAddress);
|
||||
const { value: totalSupply } = await this._erc20Client.getTotalSupply(block.hash, 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
|
||||
});
|
||||
token.symbol = symbol;
|
||||
token.name = name;
|
||||
token.totalSupply = totalSupply;
|
||||
|
||||
return this._db.saveToken(token, block);
|
||||
}
|
||||
|
||||
async _handleInitialize (block: Block, contractAddress: string, tx: Transaction, initializeEvent: InitializeEvent): Promise<void> {
|
||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
||||
const { number: blockNumber } = block;
|
||||
const { sqrtPriceX96, tick } = initializeEvent;
|
||||
const pool = await this._db.getPool({ id: contractAddress, blockNumber });
|
||||
assert(pool, `Pool ${contractAddress} not found.`);
|
||||
@ -260,39 +282,41 @@ export class Indexer {
|
||||
// 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, blockTimestamp });
|
||||
await updatePoolHourData(this._db, { contractAddress, blockNumber, blockTimestamp });
|
||||
this._db.savePool(pool, block);
|
||||
|
||||
// Update token prices.
|
||||
const [token0, token1] = await Promise.all([
|
||||
this._db.getToken({ id: pool.token0.id, blockNumber }),
|
||||
this._db.getToken({ id: pool.token1.id, blockNumber })
|
||||
]);
|
||||
|
||||
// Update ETH price now that prices could have changed.
|
||||
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||
assert(bundle);
|
||||
bundle.ethPriceUSD = await getEthPriceInUSD(this._db);
|
||||
this._db.saveBundle(bundle, block);
|
||||
|
||||
await updatePoolDayData(this._db, { contractAddress, block });
|
||||
await updatePoolHourData(this._db, { contractAddress, block });
|
||||
|
||||
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)
|
||||
this._db.saveToken(token0, block),
|
||||
this._db.saveToken(token1, block)
|
||||
]);
|
||||
}
|
||||
|
||||
async _handleMint (block: Block, contractAddress: string, tx: Transaction, mintEvent: MintEvent): Promise<void> {
|
||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
||||
const { hash: txHash } = tx;
|
||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
||||
const { number: blockNumber } = block;
|
||||
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||
assert(bundle);
|
||||
const poolAddress = contractAddress;
|
||||
const pool = await this._db.loadPool({ id: poolAddress, blockNumber });
|
||||
const pool = await this._db.getPool({ id: poolAddress, blockNumber });
|
||||
assert(pool);
|
||||
|
||||
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||
// Currently fetching first factory in database as only one exists.
|
||||
@ -349,29 +373,27 @@ export class Indexer {
|
||||
factory.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH);
|
||||
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
||||
|
||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
||||
const transaction = await loadTransaction(this._db, { block, tx });
|
||||
|
||||
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,
|
||||
const mint = new Mint();
|
||||
mint.id = transaction.id + '#' + pool.txCount.toString();
|
||||
mint.transaction = transaction;
|
||||
mint.timestamp = transaction.timestamp;
|
||||
mint.pool = pool;
|
||||
mint.token0 = pool.token0;
|
||||
mint.token1 = pool.token1;
|
||||
mint.owner = mintEvent.owner;
|
||||
mint.sender = mintEvent.sender;
|
||||
|
||||
// TODO: Assign origin with Transaction from address.
|
||||
// origin: event.transaction.from
|
||||
// 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
|
||||
});
|
||||
mint.amount = mintEvent.amount;
|
||||
mint.amount0 = amount0;
|
||||
mint.amount1 = amount1;
|
||||
mint.amountUSD = amountUSD;
|
||||
mint.tickLower = mintEvent.tickLower;
|
||||
mint.tickUpper = mintEvent.tickUpper;
|
||||
|
||||
// Tick entities.
|
||||
const lowerTickIdx = mintEvent.tickLower;
|
||||
@ -380,8 +402,16 @@ export class Indexer {
|
||||
const lowerTickId = poolAddress + '#' + mintEvent.tickLower.toString();
|
||||
const upperTickId = poolAddress + '#' + mintEvent.tickUpper.toString();
|
||||
|
||||
const lowerTick = await loadTick(this._db, lowerTickId, BigInt(lowerTickIdx), pool, blockNumber);
|
||||
const upperTick = await loadTick(this._db, upperTickId, BigInt(upperTickIdx), pool, blockNumber);
|
||||
let lowerTick = await this._db.getTick({ id: lowerTickId, blockNumber });
|
||||
let upperTick = await this._db.getTick({ id: upperTickId, blockNumber });
|
||||
|
||||
if (!lowerTick) {
|
||||
lowerTick = await createTick(this._db, lowerTickId, BigInt(lowerTickIdx), pool, block);
|
||||
}
|
||||
|
||||
if (!upperTick) {
|
||||
upperTick = await createTick(this._db, upperTickId, BigInt(upperTickIdx), pool, block);
|
||||
}
|
||||
|
||||
const amount = BigInt(mintEvent.amount);
|
||||
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) + amount;
|
||||
@ -392,36 +422,38 @@ export class Indexer {
|
||||
// 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, blockTimestamp });
|
||||
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateTokenDayData(this._db, token1, { blockNumber, blockTimestamp });
|
||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateTokenHourData(this._db, token1, { blockNumber, blockTimestamp });
|
||||
await updateUniswapDayData(this._db, { block, contractAddress });
|
||||
await updatePoolDayData(this._db, { block, contractAddress });
|
||||
await updatePoolHourData(this._db, { block, contractAddress });
|
||||
await updateTokenDayData(this._db, token0, { block });
|
||||
await updateTokenDayData(this._db, token1, { block });
|
||||
await updateTokenHourData(this._db, token0, { block });
|
||||
await updateTokenHourData(this._db, token1, { block });
|
||||
|
||||
await Promise.all([
|
||||
this._db.saveToken(token0, blockNumber),
|
||||
this._db.saveToken(token1, blockNumber)
|
||||
this._db.saveToken(token0, block),
|
||||
this._db.saveToken(token1, block)
|
||||
]);
|
||||
|
||||
await this._db.savePool(pool, blockNumber);
|
||||
await this._db.saveFactory(factory, blockNumber);
|
||||
await this._db.savePool(pool, block);
|
||||
await this._db.saveFactory(factory, block);
|
||||
await this._db.saveMint(mint, block);
|
||||
|
||||
await Promise.all([
|
||||
await this._db.saveTick(lowerTick, blockNumber),
|
||||
await this._db.saveTick(upperTick, blockNumber)
|
||||
await this._db.saveTick(lowerTick, block),
|
||||
await this._db.saveTick(upperTick, block)
|
||||
]);
|
||||
|
||||
// Skipping update inner tick vars and tick day data as they are not queried.
|
||||
}
|
||||
|
||||
async _handleBurn (block: Block, contractAddress: string, tx: Transaction, burnEvent: BurnEvent): Promise<void> {
|
||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
||||
const { hash: txHash } = tx;
|
||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
||||
const { number: blockNumber } = block;
|
||||
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||
assert(bundle);
|
||||
const poolAddress = contractAddress;
|
||||
const pool = await this._db.loadPool({ id: poolAddress, blockNumber });
|
||||
const pool = await this._db.getPool({ id: poolAddress, blockNumber });
|
||||
assert(pool);
|
||||
|
||||
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||
// Currently fetching first factory in database as only one exists.
|
||||
@ -479,74 +511,75 @@ export class Indexer {
|
||||
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
||||
|
||||
// Burn entity.
|
||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
||||
const transaction = await loadTransaction(this._db, { block, tx });
|
||||
|
||||
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,
|
||||
const burn = new Burn();
|
||||
burn.id = transaction.id + '#' + pool.txCount.toString();
|
||||
burn.transaction = transaction;
|
||||
burn.timestamp = transaction.timestamp;
|
||||
burn.pool = pool;
|
||||
burn.token0 = pool.token0;
|
||||
burn.token1 = pool.token1;
|
||||
burn.owner = burnEvent.owner;
|
||||
|
||||
// TODO: Assign origin with Transaction from address.
|
||||
// origin: event.transaction.from
|
||||
// TODO: Assign origin with Transaction from address.
|
||||
// origin: event.transaction.from
|
||||
|
||||
amount: burnEvent.amount,
|
||||
amount0,
|
||||
amount1,
|
||||
amountUSD,
|
||||
tickLower: burnEvent.tickLower,
|
||||
tickUpper: burnEvent.tickUpper
|
||||
});
|
||||
burn.amount = burnEvent.amount;
|
||||
burn.amount0 = amount0;
|
||||
burn.amount1 = amount1;
|
||||
burn.amountUSD = amountUSD;
|
||||
burn.tickLower = burnEvent.tickLower;
|
||||
burn.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 lowerTick = await this._db.getTick({ id: lowerTickId, blockNumber });
|
||||
const upperTick = await this._db.getTick({ id: upperTickId, blockNumber });
|
||||
assert(lowerTick && upperTick);
|
||||
const amount = BigInt(burnEvent.amount);
|
||||
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) - amount;
|
||||
lowerTick.liquidityNet = BigInt(lowerTick.liquidityNet) - amount;
|
||||
upperTick.liquidityGross = BigInt(upperTick.liquidityGross) - amount;
|
||||
upperTick.liquidityNet = BigInt(upperTick.liquidityNet) + amount;
|
||||
|
||||
await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
await updateUniswapDayData(this._db, { block, contractAddress });
|
||||
await updatePoolDayData(this._db, { block, contractAddress });
|
||||
await updatePoolHourData(this._db, { block, contractAddress });
|
||||
await updateTokenDayData(this._db, token0, { block });
|
||||
await updateTokenDayData(this._db, token0, { block });
|
||||
await updateTokenHourData(this._db, token0, { block });
|
||||
await updateTokenHourData(this._db, token0, { block });
|
||||
|
||||
// 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 this._db.saveTick(lowerTick, block),
|
||||
await this._db.saveTick(upperTick, block)
|
||||
]);
|
||||
|
||||
await Promise.all([
|
||||
this._db.saveToken(token0, blockNumber),
|
||||
this._db.saveToken(token1, blockNumber)
|
||||
this._db.saveToken(token0, block),
|
||||
this._db.saveToken(token1, block)
|
||||
]);
|
||||
|
||||
await this._db.savePool(pool, blockNumber);
|
||||
await this._db.saveFactory(factory, blockNumber);
|
||||
await this._db.savePool(pool, block);
|
||||
await this._db.saveFactory(factory, block);
|
||||
await this._db.saveBurn(burn, block);
|
||||
}
|
||||
|
||||
async _handleSwap (block: Block, contractAddress: string, tx: Transaction, swapEvent: SwapEvent): Promise<void> {
|
||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
||||
const { hash: txHash } = tx;
|
||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
||||
const { number: blockNumber } = block;
|
||||
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||
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.getFactories({ blockNumber }, { limit: 1 });
|
||||
|
||||
const pool = await this._db.loadPool({ id: contractAddress, blockNumber });
|
||||
const pool = await this._db.getPool({ id: contractAddress, blockNumber });
|
||||
assert(pool);
|
||||
|
||||
// Hot fix for bad pricing.
|
||||
if (pool.id === '0x9663f2ca0454accad3e094448ea6f77443880454') {
|
||||
@ -637,11 +670,11 @@ export class Indexer {
|
||||
const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token);
|
||||
pool.token0Price = prices[0];
|
||||
pool.token1Price = prices[1];
|
||||
this._db.savePool(pool, blockNumber);
|
||||
this._db.savePool(pool, block);
|
||||
|
||||
// Update USD pricing.
|
||||
bundle.ethPriceUSD = await getEthPriceInUSD(this._db);
|
||||
this._db.saveBundle(bundle, blockNumber);
|
||||
this._db.saveBundle(bundle, block);
|
||||
token0.derivedETH = await findEthPerToken(token0);
|
||||
token1.derivedETH = await findEthPerToken(token1);
|
||||
|
||||
@ -661,39 +694,37 @@ export class Indexer {
|
||||
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH).times(bundle.ethPriceUSD);
|
||||
|
||||
// Create Swap event
|
||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
||||
const transaction = await loadTransaction(this._db, { block, tx });
|
||||
|
||||
await this._db.loadSwap({
|
||||
id: transaction.id + '#' + pool.txCount.toString(),
|
||||
blockNumber,
|
||||
transaction,
|
||||
timestamp: transaction.timestamp,
|
||||
pool,
|
||||
token0: pool.token0,
|
||||
token1: pool.token1,
|
||||
sender: swapEvent.sender,
|
||||
const swap = new Swap();
|
||||
swap.id = transaction.id + '#' + pool.txCount.toString();
|
||||
swap.transaction = transaction;
|
||||
swap.timestamp = transaction.timestamp;
|
||||
swap.pool = pool;
|
||||
swap.token0 = pool.token0;
|
||||
swap.token1 = pool.token1;
|
||||
swap.sender = swapEvent.sender;
|
||||
|
||||
// TODO: Assign origin with Transaction from address.
|
||||
// origin: event.transaction.from
|
||||
// TODO: Assign origin with Transaction from address.
|
||||
// origin: event.transaction.from
|
||||
|
||||
recipient: swapEvent.recipient,
|
||||
amount0: amount0,
|
||||
amount1: amount1,
|
||||
amountUSD: amountTotalUSDTracked,
|
||||
tick: BigInt(swapEvent.tick),
|
||||
sqrtPriceX96: swapEvent.sqrtPriceX96
|
||||
});
|
||||
swap.recipient = swapEvent.recipient;
|
||||
swap.amount0 = amount0;
|
||||
swap.amount1 = amount1;
|
||||
swap.amountUSD = amountTotalUSDTracked;
|
||||
swap.tick = BigInt(swapEvent.tick);
|
||||
swap.sqrtPriceX96 = swapEvent.sqrtPriceX96;
|
||||
|
||||
// Skipping update pool fee growth as they are not queried.
|
||||
|
||||
// Interval data.
|
||||
const uniswapDayData = await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
const poolDayData = await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
const poolHourData = await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||
const token0DayData = await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
const token1DayData = await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
const token0HourData = await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
const token1HourData = await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
||||
const uniswapDayData = await updateUniswapDayData(this._db, { block, contractAddress });
|
||||
const poolDayData = await updatePoolDayData(this._db, { block, contractAddress });
|
||||
const poolHourData = await updatePoolHourData(this._db, { block, contractAddress });
|
||||
const token0DayData = await updateTokenDayData(this._db, token0, { block });
|
||||
const token1DayData = await updateTokenDayData(this._db, token0, { block });
|
||||
const token0HourData = await updateTokenHourData(this._db, token0, { block });
|
||||
const token1HourData = await updateTokenHourData(this._db, token0, { block });
|
||||
|
||||
// Update volume metrics.
|
||||
uniswapDayData.volumeETH = uniswapDayData.volumeETH.plus(amountTotalETHTracked);
|
||||
@ -730,20 +761,20 @@ export class Indexer {
|
||||
token1HourData.untrackedVolumeUSD = token1HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked);
|
||||
token1HourData.feesUSD = token1HourData.feesUSD.plus(feesUSD);
|
||||
|
||||
this._db.saveTokenDayData(token0DayData, blockNumber);
|
||||
this._db.saveTokenDayData(token1DayData, blockNumber);
|
||||
this._db.saveUniswapDayData(uniswapDayData, blockNumber);
|
||||
this._db.savePoolDayData(poolDayData, blockNumber);
|
||||
this._db.saveFactory(factory, blockNumber);
|
||||
this._db.savePool(pool, blockNumber);
|
||||
this._db.saveToken(token0, blockNumber);
|
||||
this._db.saveToken(token1, blockNumber);
|
||||
await this._db.saveSwap(swap, block);
|
||||
await this._db.saveTokenDayData(token0DayData, block);
|
||||
await this._db.saveTokenDayData(token1DayData, block);
|
||||
await this._db.saveUniswapDayData(uniswapDayData, block);
|
||||
await this._db.savePoolDayData(poolDayData, block);
|
||||
await this._db.saveFactory(factory, block);
|
||||
await this._db.savePool(pool, block);
|
||||
await this._db.saveToken(token0, block);
|
||||
await this._db.saveToken(token1, block);
|
||||
|
||||
// Skipping update of inner vars of current or crossed ticks as they are not queried.
|
||||
}
|
||||
|
||||
async _handleIncreaseLiquidity (block: Block, contractAddress: string, tx: Transaction, event: IncreaseLiquidityEvent): Promise<void> {
|
||||
const { number: blockNumber } = block;
|
||||
const position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||
|
||||
// position was not able to be fetched.
|
||||
@ -768,14 +799,13 @@ export class Indexer {
|
||||
|
||||
await this._updateFeeVars(position, block, contractAddress, BigInt(event.tokenId));
|
||||
|
||||
await this._db.savePosition(position, blockNumber);
|
||||
await this._db.savePosition(position, block);
|
||||
|
||||
await this._savePositionSnapshot(position, block, tx);
|
||||
}
|
||||
|
||||
async _handleDecreaseLiquidity (block: Block, contractAddress: string, tx: Transaction, event: DecreaseLiquidityEvent): Promise<void> {
|
||||
const { number: blockNumber } = block;
|
||||
const position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||
let position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||
|
||||
// Position was not able to be fetched.
|
||||
if (position == null) {
|
||||
@ -796,15 +826,14 @@ export class Indexer {
|
||||
position.depositedToken0 = position.depositedToken0.plus(amount0);
|
||||
position.depositedToken1 = position.depositedToken1.plus(amount1);
|
||||
|
||||
await this._updateFeeVars(position, block, contractAddress, BigInt(event.tokenId));
|
||||
position = await this._updateFeeVars(position, block, contractAddress, BigInt(event.tokenId));
|
||||
|
||||
await this._db.savePosition(position, blockNumber);
|
||||
await this._db.savePosition(position, block);
|
||||
|
||||
await this._savePositionSnapshot(position, block, tx);
|
||||
}
|
||||
|
||||
async _handleCollect (block: Block, contractAddress: string, tx: Transaction, event: CollectEvent): Promise<void> {
|
||||
const { number: blockNumber } = block;
|
||||
let position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||
|
||||
// Position was not able to be fetched.
|
||||
@ -826,7 +855,7 @@ export class Indexer {
|
||||
|
||||
position = await this._updateFeeVars(position, block, contractAddress, BigInt(event.tokenId));
|
||||
|
||||
await this._db.savePosition(position, blockNumber);
|
||||
await this._db.savePosition(position, block);
|
||||
|
||||
await this._savePositionSnapshot(position, block, tx);
|
||||
}
|
||||
@ -839,14 +868,13 @@ export class Indexer {
|
||||
}
|
||||
|
||||
position.owner = event.to;
|
||||
await this._db.savePosition(position, block.number);
|
||||
await this._db.savePosition(position, block);
|
||||
|
||||
await this._savePositionSnapshot(position, block, tx);
|
||||
}
|
||||
|
||||
async _getPosition (block: Block, contractAddress: string, tx: Transaction, tokenId: bigint): Promise<Position | null> {
|
||||
const { number: blockNumber, hash: blockHash, timestamp: blockTimestamp } = block;
|
||||
const { hash: txHash } = tx;
|
||||
const { number: blockNumber, hash: blockHash } = block;
|
||||
let position = await this._db.getPosition({ id: tokenId.toString(), blockNumber });
|
||||
|
||||
if (!position) {
|
||||
@ -861,31 +889,36 @@ export class Indexer {
|
||||
|
||||
const { pool: poolAddress } = await this._uniClient.getPool(blockHash, token0Address, token1Address, fee);
|
||||
|
||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
||||
position = new Position();
|
||||
position.id = tokenId.toString();
|
||||
|
||||
const pool = await this._db.getPool({ id: poolAddress, blockNumber });
|
||||
assert(pool);
|
||||
position.pool = pool;
|
||||
|
||||
const [token0, token1] = await Promise.all([
|
||||
this._db.getToken({ id: token0Address, blockNumber }),
|
||||
this._db.getToken({ id: token0Address, blockNumber })
|
||||
]);
|
||||
assert(token0 && token1);
|
||||
position.token0 = token0;
|
||||
position.token1 = token1;
|
||||
|
||||
const [tickLower, tickUpper] = await Promise.all([
|
||||
this._db.getTick({ id: poolAddress.concat('#').concat(nfpmPosition.tickLower.toString()), blockNumber }),
|
||||
this._db.getTick({ id: poolAddress.concat('#').concat(nfpmPosition.tickUpper.toString()), blockNumber })
|
||||
]);
|
||||
assert(tickLower && tickUpper);
|
||||
position.tickLower = tickLower;
|
||||
position.tickUpper = tickUpper;
|
||||
|
||||
position = await this._db.loadPosition({
|
||||
id: tokenId.toString(),
|
||||
blockNumber,
|
||||
pool,
|
||||
token0,
|
||||
token1,
|
||||
tickLower,
|
||||
tickUpper,
|
||||
transaction,
|
||||
feeGrowthInside0LastX128: BigInt(nfpmPosition.feeGrowthInside0LastX128.toString()),
|
||||
feeGrowthInside1LastX128: BigInt(nfpmPosition.feeGrowthInside1LastX128.toString())
|
||||
});
|
||||
const transaction = await loadTransaction(this._db, { block, tx });
|
||||
position.transaction = transaction;
|
||||
|
||||
position.feeGrowthInside0LastX128 = BigInt(nfpmPosition.feeGrowthInside0LastX128.toString());
|
||||
position.feeGrowthInside1LastX128 = BigInt(nfpmPosition.feeGrowthInside1LastX128.toString());
|
||||
|
||||
position = await this._db.savePosition(position, block);
|
||||
}
|
||||
}
|
||||
|
||||
@ -904,25 +937,24 @@ export class Indexer {
|
||||
}
|
||||
|
||||
async _savePositionSnapshot (position: Position, block: Block, tx: Transaction): Promise<void> {
|
||||
const transaction = await loadTransaction(this._db, { txHash: tx.hash, blockNumber: block.number, blockTimestamp: block.timestamp });
|
||||
const positionSnapshot = new PositionSnapshot();
|
||||
positionSnapshot.id = position.id.concat('#').concat(block.number.toString());
|
||||
positionSnapshot.blockNumber = block.number;
|
||||
positionSnapshot.owner = position.owner;
|
||||
positionSnapshot.pool = position.pool;
|
||||
positionSnapshot.position = position;
|
||||
positionSnapshot.timestamp = BigInt(block.timestamp);
|
||||
positionSnapshot.liquidity = position.liquidity;
|
||||
positionSnapshot.depositedToken0 = position.depositedToken0;
|
||||
positionSnapshot.depositedToken1 = position.depositedToken1;
|
||||
positionSnapshot.withdrawnToken0 = position.withdrawnToken0;
|
||||
positionSnapshot.withdrawnToken1 = position.withdrawnToken1;
|
||||
positionSnapshot.collectedFeesToken0 = position.collectedFeesToken0;
|
||||
positionSnapshot.collectedFeesToken1 = position.collectedFeesToken1;
|
||||
positionSnapshot.transaction = await loadTransaction(this._db, { block, tx });
|
||||
positionSnapshot.feeGrowthInside0LastX128 = position.feeGrowthInside0LastX128;
|
||||
positionSnapshot.feeGrowthInside1LastX128 = position.feeGrowthInside1LastX128;
|
||||
|
||||
await this._db.loadPositionSnapshot({
|
||||
id: position.id.concat('#').concat(block.number.toString()),
|
||||
blockNumber: block.number,
|
||||
owner: position.owner,
|
||||
pool: position.pool,
|
||||
position: position,
|
||||
timestamp: block.timestamp,
|
||||
liquidity: position.liquidity,
|
||||
depositedToken0: position.depositedToken0,
|
||||
depositedToken1: position.depositedToken1,
|
||||
withdrawnToken0: position.withdrawnToken0,
|
||||
withdrawnToken1: position.withdrawnToken1,
|
||||
collectedFeesToken0: position.collectedFeesToken0,
|
||||
collectedFeesToken1: position.collectedFeesToken1,
|
||||
transaction,
|
||||
feeGrowthInside0LastX128: position.feeGrowthInside0LastX128,
|
||||
feeGrowthInside1LastX128: position.feeGrowthInside1LastX128
|
||||
});
|
||||
await this._db.savePositionSnapshot(positionSnapshot, block);
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import Decimal from 'decimal.js';
|
||||
import { BigNumber } from 'ethers';
|
||||
|
||||
import { Transaction } from '../entity/Transaction';
|
||||
import { Transaction as TransactionEntity } from '../entity/Transaction';
|
||||
import { Database } from '../database';
|
||||
import { Block, Transaction } from '../events';
|
||||
|
||||
export const exponentToBigDecimal = (decimals: bigint): Decimal => {
|
||||
let bd = new Decimal(1);
|
||||
@ -22,19 +23,19 @@ export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: big
|
||||
return (new Decimal(tokenAmount.toString())).div(exponentToBigDecimal(exchangeDecimals));
|
||||
};
|
||||
|
||||
export const loadTransaction = async (db: Database, event: { txHash: string, blockNumber: number, blockTimestamp: number }): Promise<Transaction> => {
|
||||
const { txHash, blockNumber, blockTimestamp } = event;
|
||||
export const loadTransaction = async (db: Database, event: { block: Block, tx: Transaction }): Promise<TransactionEntity> => {
|
||||
const { tx, block } = event;
|
||||
let transaction = await db.getTransaction({ id: tx.hash, blockNumber: block.number });
|
||||
|
||||
const transaction = await db.loadTransaction({
|
||||
id: txHash,
|
||||
blockNumber,
|
||||
timestamp: BigInt(blockTimestamp)
|
||||
});
|
||||
if (!transaction) {
|
||||
transaction = new TransactionEntity();
|
||||
transaction.id = tx.hash;
|
||||
}
|
||||
|
||||
transaction.blockNumber = blockNumber;
|
||||
transaction.timestamp = BigInt(blockTimestamp);
|
||||
transaction.blockNumber = block.number;
|
||||
transaction.timestamp = BigInt(block.timestamp);
|
||||
|
||||
return db.saveTransaction(transaction, blockNumber);
|
||||
return db.saveTransaction(transaction, block);
|
||||
};
|
||||
|
||||
// Return 0 if denominator is 0 in division.
|
||||
|
@ -1,3 +1,4 @@
|
||||
import assert from 'assert';
|
||||
import { BigNumber } from 'ethers';
|
||||
|
||||
import { Database } from '../database';
|
||||
@ -7,56 +8,63 @@ import { Token } from '../entity/Token';
|
||||
import { TokenDayData } from '../entity/TokenDayData';
|
||||
import { TokenHourData } from '../entity/TokenHourData';
|
||||
import { UniswapDayData } from '../entity/UniswapDayData';
|
||||
import { Block } from '../events';
|
||||
|
||||
/**
|
||||
* Tracks global aggregate data over daily windows.
|
||||
* @param db
|
||||
* @param event
|
||||
*/
|
||||
export const updateUniswapDayData = async (db: Database, event: { contractAddress: string, blockNumber: number, blockTimestamp: number }): Promise<UniswapDayData> => {
|
||||
const { blockNumber, blockTimestamp } = event;
|
||||
export const updateUniswapDayData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<UniswapDayData> => {
|
||||
const { block } = event;
|
||||
|
||||
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||
// Currently fetching first factory in database as only one exists.
|
||||
const [factory] = await db.getFactories({ blockNumber }, { limit: 1 });
|
||||
const [factory] = await db.getFactories({ blockNumber: block.number }, { limit: 1 });
|
||||
|
||||
const dayID = Math.floor(blockTimestamp / 86400); // Rounded.
|
||||
const dayID = Math.floor(block.timestamp / 86400); // Rounded.
|
||||
const dayStartTimestamp = dayID * 86400;
|
||||
|
||||
const uniswapDayData = await db.loadUniswapDayData({
|
||||
id: dayID.toString(),
|
||||
blockNumber,
|
||||
date: dayStartTimestamp,
|
||||
tvlUSD: factory.totalValueLockedUSD,
|
||||
txCount: factory.txCount
|
||||
});
|
||||
let uniswapDayData = await db.getUniswapDayData({ id: dayID.toString(), blockNumber: block.number });
|
||||
|
||||
if (!uniswapDayData) {
|
||||
uniswapDayData = new UniswapDayData();
|
||||
uniswapDayData.id = dayID.toString();
|
||||
uniswapDayData.date = dayStartTimestamp;
|
||||
uniswapDayData.tvlUSD = factory.totalValueLockedUSD;
|
||||
uniswapDayData.txCount = factory.txCount;
|
||||
}
|
||||
|
||||
uniswapDayData.tvlUSD = factory.totalValueLockedUSD;
|
||||
uniswapDayData.txCount = factory.txCount;
|
||||
return db.saveUniswapDayData(uniswapDayData, blockNumber);
|
||||
return db.saveUniswapDayData(uniswapDayData, block);
|
||||
};
|
||||
|
||||
export const updatePoolDayData = async (db: Database, event: { contractAddress: string, blockNumber: number, blockTimestamp: number }): Promise<PoolDayData> => {
|
||||
const { contractAddress, blockNumber, blockTimestamp } = event;
|
||||
const dayID = Math.floor(blockTimestamp / 86400);
|
||||
export const updatePoolDayData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<PoolDayData> => {
|
||||
const { contractAddress, block } = event;
|
||||
const dayID = Math.floor(block.timestamp / 86400);
|
||||
const dayStartTimestamp = dayID * 86400;
|
||||
|
||||
const dayPoolID = contractAddress
|
||||
.concat('-')
|
||||
.concat(dayID.toString());
|
||||
|
||||
const pool = await db.loadPool({ id: contractAddress, blockNumber });
|
||||
const pool = await db.getPool({ id: contractAddress, blockNumber: block.number });
|
||||
assert(pool);
|
||||
|
||||
let poolDayData = await db.loadPoolDayData({
|
||||
id: dayPoolID,
|
||||
blockNumber,
|
||||
date: dayStartTimestamp,
|
||||
pool: pool,
|
||||
open: pool.token0Price,
|
||||
high: pool.token0Price,
|
||||
low: pool.token0Price,
|
||||
close: pool.token0Price
|
||||
});
|
||||
let poolDayData = await db.getPoolDayData({ id: dayPoolID, blockNumber: block.number });
|
||||
|
||||
if (!poolDayData) {
|
||||
poolDayData = new PoolDayData();
|
||||
poolDayData.id = dayPoolID;
|
||||
poolDayData.date = dayStartTimestamp;
|
||||
poolDayData.pool = pool;
|
||||
poolDayData.open = pool.token0Price;
|
||||
poolDayData.high = pool.token0Price;
|
||||
poolDayData.low = pool.token0Price;
|
||||
poolDayData.close = pool.token0Price;
|
||||
poolDayData = await db.savePoolDayData(poolDayData, block);
|
||||
}
|
||||
|
||||
if (Number(pool.token0Price) > Number(poolDayData.high)) {
|
||||
poolDayData.high = pool.token0Price;
|
||||
@ -75,32 +83,36 @@ export const updatePoolDayData = async (db: Database, event: { contractAddress:
|
||||
poolDayData.tick = pool.tick;
|
||||
poolDayData.tvlUSD = pool.totalValueLockedUSD;
|
||||
poolDayData.txCount = BigInt(BigNumber.from(poolDayData.txCount).add(1).toHexString());
|
||||
poolDayData = await db.savePoolDayData(poolDayData, blockNumber);
|
||||
poolDayData = await db.savePoolDayData(poolDayData, block);
|
||||
|
||||
return poolDayData;
|
||||
};
|
||||
|
||||
export const updatePoolHourData = async (db: Database, event: { contractAddress: string, blockNumber: number, blockTimestamp: number }): Promise<PoolHourData> => {
|
||||
const { contractAddress, blockNumber, blockTimestamp } = event;
|
||||
const hourIndex = Math.floor(blockTimestamp / 3600); // Get unique hour within unix history.
|
||||
export const updatePoolHourData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<PoolHourData> => {
|
||||
const { contractAddress, block } = event;
|
||||
const hourIndex = Math.floor(block.timestamp / 3600); // Get unique hour within unix history.
|
||||
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
||||
|
||||
const hourPoolID = contractAddress
|
||||
.concat('-')
|
||||
.concat(hourIndex.toString());
|
||||
|
||||
const pool = await db.loadPool({ id: contractAddress, blockNumber });
|
||||
const pool = await db.getPool({ id: contractAddress, blockNumber: block.number });
|
||||
assert(pool);
|
||||
|
||||
let poolHourData = await db.loadPoolHourData({
|
||||
id: hourPoolID,
|
||||
blockNumber,
|
||||
periodStartUnix: hourStartUnix,
|
||||
pool: pool,
|
||||
open: pool.token0Price,
|
||||
high: pool.token0Price,
|
||||
low: pool.token0Price,
|
||||
close: pool.token0Price
|
||||
});
|
||||
let poolHourData = await db.getPoolHourData({ id: hourPoolID, blockNumber: block.number });
|
||||
|
||||
if (!poolHourData) {
|
||||
poolHourData = new PoolHourData();
|
||||
poolHourData.id = hourPoolID;
|
||||
poolHourData.periodStartUnix = hourStartUnix;
|
||||
poolHourData.pool = pool;
|
||||
poolHourData.open = pool.token0Price;
|
||||
poolHourData.high = pool.token0Price;
|
||||
poolHourData.low = pool.token0Price;
|
||||
poolHourData.close = pool.token0Price;
|
||||
poolHourData = await db.savePoolHourData(poolHourData, block);
|
||||
}
|
||||
|
||||
if (Number(pool.token0Price) > Number(poolHourData.high)) {
|
||||
poolHourData.high = pool.token0Price;
|
||||
@ -119,15 +131,16 @@ export const updatePoolHourData = async (db: Database, event: { contractAddress:
|
||||
poolHourData.tick = pool.tick;
|
||||
poolHourData.tvlUSD = pool.totalValueLockedUSD;
|
||||
poolHourData.txCount = BigInt(BigNumber.from(poolHourData.txCount).add(1).toHexString());
|
||||
poolHourData = await db.savePoolHourData(poolHourData, blockNumber);
|
||||
poolHourData = await db.savePoolHourData(poolHourData, block);
|
||||
|
||||
return poolHourData;
|
||||
};
|
||||
|
||||
export const updateTokenDayData = async (db: Database, token: Token, event: { blockNumber: number, blockTimestamp: number }): Promise<TokenDayData> => {
|
||||
const { blockNumber, blockTimestamp } = event;
|
||||
const bundle = await db.loadBundle({ id: '1', blockNumber });
|
||||
const dayID = Math.floor(blockTimestamp / 86400);
|
||||
export const updateTokenDayData = async (db: Database, token: Token, event: { block: Block }): Promise<TokenDayData> => {
|
||||
const { block } = event;
|
||||
const bundle = await db.getBundle({ id: '1', blockNumber: block.number });
|
||||
assert(bundle);
|
||||
const dayID = Math.floor(block.timestamp / 86400);
|
||||
const dayStartTimestamp = dayID * 86400;
|
||||
|
||||
const tokenDayID = token.id
|
||||
@ -136,19 +149,21 @@ export const updateTokenDayData = async (db: Database, token: Token, event: { bl
|
||||
|
||||
const tokenPrice = token.derivedETH.times(bundle.ethPriceUSD);
|
||||
|
||||
const tokenDayData = await db.loadTokenDayData({
|
||||
id: tokenDayID,
|
||||
blockNumber,
|
||||
date: dayStartTimestamp,
|
||||
token,
|
||||
open: tokenPrice,
|
||||
high: tokenPrice,
|
||||
low: tokenPrice,
|
||||
close: tokenPrice,
|
||||
priceUSD: token.derivedETH.times(bundle.ethPriceUSD),
|
||||
totalValueLocked: token.totalValueLocked,
|
||||
totalValueLockedUSD: token.totalValueLockedUSD
|
||||
});
|
||||
let tokenDayData = await db.getTokenDayData({ id: tokenDayID, blockNumber: block.number });
|
||||
|
||||
if (!tokenDayData) {
|
||||
tokenDayData = new TokenDayData();
|
||||
tokenDayData.id = tokenDayID;
|
||||
tokenDayData.date = dayStartTimestamp;
|
||||
tokenDayData.token = token;
|
||||
tokenDayData.open = tokenPrice;
|
||||
tokenDayData.high = tokenPrice;
|
||||
tokenDayData.low = tokenPrice;
|
||||
tokenDayData.close = tokenPrice;
|
||||
tokenDayData.priceUSD = token.derivedETH.times(bundle.ethPriceUSD);
|
||||
tokenDayData.totalValueLocked = token.totalValueLocked;
|
||||
tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||
}
|
||||
|
||||
if (tokenPrice.gt(tokenDayData.high)) {
|
||||
tokenDayData.high = tokenPrice;
|
||||
@ -162,13 +177,14 @@ export const updateTokenDayData = async (db: Database, token: Token, event: { bl
|
||||
tokenDayData.priceUSD = token.derivedETH.times(bundle.ethPriceUSD);
|
||||
tokenDayData.totalValueLocked = token.totalValueLocked;
|
||||
tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||
return db.saveTokenDayData(tokenDayData, blockNumber);
|
||||
return db.saveTokenDayData(tokenDayData, block);
|
||||
};
|
||||
|
||||
export const updateTokenHourData = async (db: Database, token: Token, event: { blockNumber: number, blockTimestamp: number }): Promise<TokenHourData> => {
|
||||
const { blockNumber, blockTimestamp } = event;
|
||||
const bundle = await db.loadBundle({ id: '1', blockNumber });
|
||||
const hourIndex = Math.floor(blockTimestamp / 3600); // Get unique hour within unix history.
|
||||
export const updateTokenHourData = async (db: Database, token: Token, event: { block: Block }): Promise<TokenHourData> => {
|
||||
const { block } = event;
|
||||
const bundle = await db.getBundle({ id: '1', blockNumber: block.number });
|
||||
assert(bundle);
|
||||
const hourIndex = Math.floor(block.timestamp / 3600); // Get unique hour within unix history.
|
||||
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
||||
|
||||
const tokenHourID = token.id
|
||||
@ -177,19 +193,21 @@ export const updateTokenHourData = async (db: Database, token: Token, event: { b
|
||||
|
||||
const tokenPrice = token.derivedETH.times(bundle.ethPriceUSD);
|
||||
|
||||
const tokenHourData = await db.loadTokenHourData({
|
||||
id: tokenHourID,
|
||||
blockNumber,
|
||||
periodStartUnix: hourStartUnix,
|
||||
token: token,
|
||||
open: tokenPrice,
|
||||
high: tokenPrice,
|
||||
low: tokenPrice,
|
||||
close: tokenPrice,
|
||||
priceUSD: tokenPrice,
|
||||
totalValueLocked: token.totalValueLocked,
|
||||
totalValueLockedUSD: token.totalValueLockedUSD
|
||||
});
|
||||
let tokenHourData = await db.getTokenHourData({ id: tokenHourID, blockNumber: block.number });
|
||||
|
||||
if (!tokenHourData) {
|
||||
tokenHourData = new TokenHourData();
|
||||
tokenHourData.id = tokenHourID;
|
||||
tokenHourData.periodStartUnix = hourStartUnix;
|
||||
tokenHourData.token = token;
|
||||
tokenHourData.open = tokenPrice;
|
||||
tokenHourData.high = tokenPrice;
|
||||
tokenHourData.low = tokenPrice;
|
||||
tokenHourData.close = tokenPrice;
|
||||
tokenHourData.priceUSD = tokenPrice;
|
||||
tokenHourData.totalValueLocked = token.totalValueLocked;
|
||||
tokenHourData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||
}
|
||||
|
||||
if (tokenPrice.gt(tokenHourData.high)) {
|
||||
tokenHourData.high = tokenPrice;
|
||||
@ -203,5 +221,5 @@ export const updateTokenHourData = async (db: Database, token: Token, event: { b
|
||||
tokenHourData.priceUSD = tokenPrice;
|
||||
tokenHourData.totalValueLocked = token.totalValueLocked;
|
||||
tokenHourData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||
return db.saveTokenHourData(tokenHourData, blockNumber);
|
||||
return db.saveTokenHourData(tokenHourData, block);
|
||||
};
|
||||
|
@ -1,3 +1,4 @@
|
||||
import assert from 'assert';
|
||||
import Decimal from 'decimal.js';
|
||||
import { BigNumber } from 'ethers';
|
||||
|
||||
@ -125,7 +126,8 @@ export const getTrackedAmountUSD = async (
|
||||
tokenAmount1: Decimal,
|
||||
token1: Token
|
||||
): Promise<Decimal> => {
|
||||
const bundle = await db.loadBundle({ id: '1' });
|
||||
const bundle = await db.getBundle({ id: '1' });
|
||||
assert(bundle);
|
||||
const price0USD = token0.derivedETH.times(bundle.ethPriceUSD);
|
||||
const price1USD = token1.derivedETH.times(bundle.ethPriceUSD);
|
||||
|
||||
|
@ -4,18 +4,20 @@ import { Pool } from '../entity/Pool';
|
||||
import { Database } from '../database';
|
||||
import { bigDecimalExponated, safeDiv } from '.';
|
||||
import { Tick } from '../entity/Tick';
|
||||
import { Block } from '../events';
|
||||
|
||||
export const createTick = async (db: Database, tickId: string, tickIdx: bigint, pool: Pool, block: Block): Promise<Tick> => {
|
||||
const tick = new Tick();
|
||||
tick.id = tickId;
|
||||
tick.tickIdx = tickIdx;
|
||||
tick.pool = pool;
|
||||
tick.poolAddress = pool.id;
|
||||
|
||||
export const loadTick = async (db: Database, tickId: string, tickIdx: bigint, pool: Pool, blockNumber: number): Promise<Tick> => {
|
||||
// 1.0001^tick is token1/token0.
|
||||
const price0 = bigDecimalExponated(new Decimal('1.0001'), tickIdx);
|
||||
|
||||
return db.loadTick({
|
||||
id: tickId,
|
||||
blockNumber,
|
||||
tickIdx: tickIdx,
|
||||
pool,
|
||||
poolAddress: pool.id,
|
||||
price0,
|
||||
price1: safeDiv(new Decimal(1), price0)
|
||||
});
|
||||
tick.price0 = price0;
|
||||
tick.price1 = safeDiv(new Decimal(1), price0);
|
||||
|
||||
return db.saveTick(tick, block);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user