mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-07-31 12:02:07 +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();
|
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> {
|
async getToken ({ id, blockNumber }: DeepPartial<Token>): Promise<Token | undefined> {
|
||||||
const repo = this._conn.getRepository(Token);
|
const repo = this._conn.getRepository(Token);
|
||||||
|
|
||||||
@ -122,6 +160,114 @@ export class Database {
|
|||||||
return repo.findOne(findOptions);
|
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>> {
|
async getFactories ({ blockNumber }: DeepPartial<Factory>, queryOptions: { [key: string]: any }): Promise<Array<Factory>> {
|
||||||
const repo = this._conn.getRepository(Factory);
|
const repo = this._conn.getRepository(Factory);
|
||||||
|
|
||||||
@ -143,485 +289,150 @@ export class Database {
|
|||||||
return selectQueryBuilder.getMany();
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Factory);
|
const repo = tx.getRepository(Factory);
|
||||||
|
factory.blockNumber = block.number;
|
||||||
let selectQueryBuilder = repo.createQueryBuilder('factory')
|
factory.blockHash = block.hash;
|
||||||
.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;
|
|
||||||
return repo.save(factory);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Bundle);
|
const repo = tx.getRepository(Bundle);
|
||||||
bundle.blockNumber = blockNumber;
|
bundle.blockNumber = block.number;
|
||||||
|
bundle.blockHash = block.hash;
|
||||||
return repo.save(bundle);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Pool);
|
const repo = tx.getRepository(Pool);
|
||||||
pool.blockNumber = blockNumber;
|
pool.blockNumber = block.number;
|
||||||
|
pool.blockHash = block.hash;
|
||||||
return repo.save(pool);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(PoolDayData);
|
const repo = tx.getRepository(PoolDayData);
|
||||||
poolDayData.blockNumber = blockNumber;
|
poolDayData.blockNumber = block.number;
|
||||||
|
poolDayData.blockHash = block.hash;
|
||||||
return repo.save(poolDayData);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(PoolHourData);
|
const repo = tx.getRepository(PoolHourData);
|
||||||
poolHourData.blockNumber = blockNumber;
|
poolHourData.blockNumber = block.number;
|
||||||
|
poolHourData.blockHash = block.hash;
|
||||||
return repo.save(poolHourData);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Token);
|
const repo = tx.getRepository(Token);
|
||||||
token.blockNumber = blockNumber;
|
token.blockNumber = block.number;
|
||||||
|
token.blockHash = block.hash;
|
||||||
return repo.save(token);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Transaction);
|
const repo = tx.getRepository(Transaction);
|
||||||
transaction.blockNumber = blockNumber;
|
transaction.blockNumber = block.number;
|
||||||
|
transaction.blockHash = block.hash;
|
||||||
return repo.save(transaction);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(UniswapDayData);
|
const repo = tx.getRepository(UniswapDayData);
|
||||||
uniswapDayData.blockNumber = blockNumber;
|
uniswapDayData.blockNumber = block.number;
|
||||||
|
uniswapDayData.blockHash = block.hash;
|
||||||
return repo.save(uniswapDayData);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(TokenDayData);
|
const repo = tx.getRepository(TokenDayData);
|
||||||
tokenDayData.blockNumber = blockNumber;
|
tokenDayData.blockNumber = block.number;
|
||||||
|
tokenDayData.blockHash = block.hash;
|
||||||
return repo.save(tokenDayData);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(TokenHourData);
|
const repo = tx.getRepository(TokenHourData);
|
||||||
tokenHourData.blockNumber = blockNumber;
|
tokenHourData.blockNumber = block.number;
|
||||||
|
tokenHourData.blockHash = block.hash;
|
||||||
return repo.save(tokenHourData);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Tick);
|
const repo = tx.getRepository(Tick);
|
||||||
tick.blockNumber = blockNumber;
|
tick.blockNumber = block.number;
|
||||||
|
tick.blockHash = block.hash;
|
||||||
return repo.save(tick);
|
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) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Position);
|
const repo = tx.getRepository(Position);
|
||||||
position.blockNumber = blockNumber;
|
position.blockNumber = block.number;
|
||||||
|
position.blockHash = block.hash;
|
||||||
return repo.save(position);
|
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.
|
// Returns true if events have already been synced for the (block, token) combination.
|
||||||
async didSyncEvents ({ blockHash, token }: { blockHash: string, token: string }): Promise<boolean> {
|
async didSyncEvents ({ blockHash, token }: { blockHash: string, token: string }): Promise<boolean> {
|
||||||
const numRows = await this._conn.getRepository(EventSyncProgress)
|
const numRows = await this._conn.getRepository(EventSyncProgress)
|
||||||
|
@ -7,7 +7,10 @@ export class Bundle {
|
|||||||
@PrimaryColumn('varchar', { length: 1 })
|
@PrimaryColumn('varchar', { length: 1 })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
@ -11,7 +11,10 @@ export class Burn {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@ManyToOne(() => Transaction, transaction => transaction.burns)
|
@ManyToOne(() => Transaction, transaction => transaction.burns)
|
||||||
|
@ -7,7 +7,10 @@ export class Factory {
|
|||||||
@PrimaryColumn('varchar', { length: 42 })
|
@PrimaryColumn('varchar', { length: 42 })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('bigint', { default: BigInt(0) })
|
@Column('bigint', { default: BigInt(0) })
|
||||||
|
@ -11,7 +11,10 @@ export class Mint {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@ManyToOne(() => Transaction, transaction => transaction.mints)
|
@ManyToOne(() => Transaction, transaction => transaction.mints)
|
||||||
|
@ -9,7 +9,10 @@ export class Pool {
|
|||||||
@PrimaryColumn('varchar', { length: 42 })
|
@PrimaryColumn('varchar', { length: 42 })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@ManyToOne(() => Token)
|
@ManyToOne(() => Token)
|
||||||
|
@ -9,7 +9,10 @@ export class PoolDayData {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('integer')
|
||||||
|
@ -9,7 +9,10 @@ export class PoolHourData {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('integer')
|
||||||
|
@ -13,7 +13,10 @@ export class Position {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('bigint')
|
@Column('bigint')
|
||||||
|
@ -12,7 +12,10 @@ export class PositionSnapshot {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('bigint')
|
@Column('bigint')
|
||||||
|
@ -11,7 +11,10 @@ export class Swap {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@ManyToOne(() => Transaction, transaction => transaction.swaps)
|
@ManyToOne(() => Transaction, transaction => transaction.swaps)
|
||||||
|
@ -9,7 +9,10 @@ export class Tick {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('bigint')
|
@Column('bigint')
|
||||||
|
@ -9,7 +9,10 @@ export class Token {
|
|||||||
@PrimaryColumn('varchar', { length: 42 })
|
@PrimaryColumn('varchar', { length: 42 })
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('varchar')
|
@Column('varchar')
|
||||||
|
@ -9,7 +9,10 @@ export class TokenDayData {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('integer')
|
||||||
|
@ -9,7 +9,10 @@ export class TokenHourData {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('integer')
|
||||||
|
@ -11,7 +11,10 @@ export class Transaction {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
@ -7,7 +7,10 @@ export class UniswapDayData {
|
|||||||
@PrimaryColumn('varchar')
|
@PrimaryColumn('varchar')
|
||||||
id!: string;
|
id!: string;
|
||||||
|
|
||||||
@PrimaryColumn('integer')
|
@PrimaryColumn('varchar', { length: 66 })
|
||||||
|
blockHash!: string
|
||||||
|
|
||||||
|
@Column('integer')
|
||||||
blockNumber!: number;
|
blockNumber!: number;
|
||||||
|
|
||||||
@Column('integer')
|
@Column('integer')
|
||||||
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
import { DeepPartial } from 'typeorm';
|
import { DeepPartial } from 'typeorm';
|
||||||
import JSONbig from 'json-bigint';
|
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 UniClient } from '@vulcanize/uni-watcher';
|
||||||
import { Client as ERC20Client } from '@vulcanize/erc20-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 { updatePoolDayData, updatePoolHourData, updateTokenDayData, updateTokenHourData, updateUniswapDayData } from './utils/interval-updates';
|
||||||
import { Token } from './entity/Token';
|
import { Token } from './entity/Token';
|
||||||
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
|
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
|
||||||
import { loadTick } from './utils/tick';
|
import { createTick } from './utils/tick';
|
||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
import { Position } from './entity/Position';
|
import { Position } from './entity/Position';
|
||||||
import { Database } from './database';
|
import { Database } from './database';
|
||||||
import { Event } from './entity/Event';
|
import { Event } from './entity/Event';
|
||||||
import { ResultEvent, Block, Transaction, PoolCreatedEvent, InitializeEvent, MintEvent, BurnEvent, SwapEvent, IncreaseLiquidityEvent, DecreaseLiquidityEvent, CollectEvent, TransferEvent } from './events';
|
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');
|
const log = debug('vulcanize:indexer');
|
||||||
|
|
||||||
@ -88,7 +95,7 @@ export class Indexer {
|
|||||||
const resultEvent = this.getResultEvent(dbEvent);
|
const resultEvent = this.getResultEvent(dbEvent);
|
||||||
|
|
||||||
// TODO: Process proof (proof.data) in event.
|
// TODO: Process proof (proof.data) in event.
|
||||||
const { contract, block, tx, event } = resultEvent;
|
const { contract, tx, block, event } = resultEvent;
|
||||||
const { __typename: eventType } = event;
|
const { __typename: eventType } = event;
|
||||||
|
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
@ -179,16 +186,33 @@ export class Indexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _handlePoolCreated (block: Block, contractAddress: string, tx: Transaction, poolCreatedEvent: PoolCreatedEvent): Promise<void> {
|
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;
|
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.
|
// 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.
|
// Update Factory.
|
||||||
let factoryPoolCount = BigNumber.from(factory.poolCount);
|
factory.poolCount = BigInt(factory.poolCount) + BigInt(1);
|
||||||
factoryPoolCount = factoryPoolCount.add(1);
|
|
||||||
factory.poolCount = BigInt(factoryPoolCount.toHexString());
|
let pool = new Pool();
|
||||||
|
pool.id = poolAddress;
|
||||||
|
|
||||||
// Get Tokens.
|
// Get Tokens.
|
||||||
let [token0, token1] = await Promise.all([
|
let [token0, token1] = await Promise.all([
|
||||||
@ -198,61 +222,59 @@ export class Indexer {
|
|||||||
|
|
||||||
// Create Tokens if not present.
|
// Create Tokens if not present.
|
||||||
if (!token0) {
|
if (!token0) {
|
||||||
token0 = await this._createToken(blockHash, blockNumber, token0Address);
|
token0 = await this._createToken(block, token0Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!token1) {
|
if (!token1) {
|
||||||
token1 = await this._createToken(blockHash, blockNumber, token1Address);
|
token1 = await this._createToken(block, token1Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new Pool entity.
|
pool.token0 = token0;
|
||||||
// Skipping adding createdAtTimestamp field as it is not queried in frontend subgraph.
|
pool.token1 = token1;
|
||||||
const pool = await this._db.loadPool({
|
pool.feeTier = BigInt(fee);
|
||||||
blockNumber,
|
pool = await this._db.savePool(pool, block);
|
||||||
id: poolAddress,
|
|
||||||
token0: token0,
|
|
||||||
token1: token1,
|
|
||||||
feeTier: BigInt(fee)
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update white listed pools.
|
// Update white listed pools.
|
||||||
if (WHITELIST_TOKENS.includes(token0.id)) {
|
if (WHITELIST_TOKENS.includes(token0.id)) {
|
||||||
token1.whitelistPools.push(pool);
|
token1.whitelistPools.push(pool);
|
||||||
await this._db.saveToken(token1, blockNumber);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WHITELIST_TOKENS.includes(token1.id)) {
|
if (WHITELIST_TOKENS.includes(token1.id)) {
|
||||||
token0.whitelistPools.push(pool);
|
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.
|
// 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.
|
* Create new Token.
|
||||||
* @param tokenAddress
|
* @param tokenAddress
|
||||||
*/
|
*/
|
||||||
async _createToken (blockHash: string, blockNumber: number, tokenAddress: string): Promise<Token> {
|
async _createToken (block: Block, tokenAddress: string): Promise<Token> {
|
||||||
const { value: symbol } = await this._erc20Client.getSymbol(blockHash, tokenAddress);
|
const token = new Token();
|
||||||
const { value: name } = await this._erc20Client.getName(blockHash, tokenAddress);
|
token.id = tokenAddress;
|
||||||
const { value: totalSupply } = await this._erc20Client.getTotalSupply(blockHash, 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.
|
// TODO: Decimals not implemented by erc20-watcher.
|
||||||
// const { value: decimals } = await this._erc20Client.getDecimals(blockHash, tokenAddress);
|
// const { value: decimals } = await this._erc20Client.getDecimals(blockHash, tokenAddress);
|
||||||
|
|
||||||
return this._db.loadToken({
|
token.symbol = symbol;
|
||||||
blockNumber,
|
token.name = name;
|
||||||
id: tokenAddress,
|
token.totalSupply = totalSupply;
|
||||||
symbol,
|
|
||||||
name,
|
return this._db.saveToken(token, block);
|
||||||
totalSupply
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleInitialize (block: Block, contractAddress: string, tx: Transaction, initializeEvent: InitializeEvent): Promise<void> {
|
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 { sqrtPriceX96, tick } = initializeEvent;
|
||||||
const pool = await this._db.getPool({ id: contractAddress, blockNumber });
|
const pool = await this._db.getPool({ id: contractAddress, blockNumber });
|
||||||
assert(pool, `Pool ${contractAddress} not found.`);
|
assert(pool, `Pool ${contractAddress} not found.`);
|
||||||
@ -260,39 +282,41 @@ export class Indexer {
|
|||||||
// Update Pool.
|
// Update Pool.
|
||||||
pool.sqrtPrice = BigInt(sqrtPriceX96);
|
pool.sqrtPrice = BigInt(sqrtPriceX96);
|
||||||
pool.tick = BigInt(tick);
|
pool.tick = BigInt(tick);
|
||||||
this._db.savePool(pool, blockNumber);
|
this._db.savePool(pool, block);
|
||||||
|
|
||||||
// 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 });
|
|
||||||
|
|
||||||
|
// Update token prices.
|
||||||
const [token0, token1] = await Promise.all([
|
const [token0, token1] = await Promise.all([
|
||||||
this._db.getToken({ id: pool.token0.id, blockNumber }),
|
this._db.getToken({ id: pool.token0.id, blockNumber }),
|
||||||
this._db.getToken({ id: pool.token1.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.');
|
assert(token0 && token1, 'Pool tokens not found.');
|
||||||
|
|
||||||
// Update token prices.
|
|
||||||
token0.derivedETH = await findEthPerToken(token0);
|
token0.derivedETH = await findEthPerToken(token0);
|
||||||
token1.derivedETH = await findEthPerToken(token1);
|
token1.derivedETH = await findEthPerToken(token1);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._db.saveToken(token0, blockNumber),
|
this._db.saveToken(token0, block),
|
||||||
this._db.saveToken(token1, blockNumber)
|
this._db.saveToken(token1, block)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleMint (block: Block, contractAddress: string, tx: Transaction, mintEvent: MintEvent): Promise<void> {
|
async _handleMint (block: Block, contractAddress: string, tx: Transaction, mintEvent: MintEvent): Promise<void> {
|
||||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
const { number: blockNumber } = block;
|
||||||
const { hash: txHash } = tx;
|
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
assert(bundle);
|
||||||
const poolAddress = contractAddress;
|
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.
|
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||||
// Currently fetching first factory in database as only one exists.
|
// 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.totalValueLockedETH = factory.totalValueLockedETH.plus(pool.totalValueLockedETH);
|
||||||
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
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({
|
const mint = new Mint();
|
||||||
id: transaction.id + '#' + pool.txCount.toString(),
|
mint.id = transaction.id + '#' + pool.txCount.toString();
|
||||||
blockNumber,
|
mint.transaction = transaction;
|
||||||
transaction,
|
mint.timestamp = transaction.timestamp;
|
||||||
timestamp: transaction.timestamp,
|
mint.pool = pool;
|
||||||
pool,
|
mint.token0 = pool.token0;
|
||||||
token0: pool.token0,
|
mint.token1 = pool.token1;
|
||||||
token1: pool.token1,
|
mint.owner = mintEvent.owner;
|
||||||
owner: mintEvent.owner,
|
mint.sender = mintEvent.sender;
|
||||||
sender: mintEvent.sender,
|
|
||||||
|
|
||||||
// TODO: Assign origin with Transaction from address.
|
// TODO: Assign origin with Transaction from address.
|
||||||
// origin: event.transaction.from
|
// origin: event.transaction.from
|
||||||
|
|
||||||
amount: mintEvent.amount,
|
mint.amount = mintEvent.amount;
|
||||||
amount0: amount0,
|
mint.amount0 = amount0;
|
||||||
amount1: amount1,
|
mint.amount1 = amount1;
|
||||||
amountUSD: amountUSD,
|
mint.amountUSD = amountUSD;
|
||||||
tickLower: mintEvent.tickLower,
|
mint.tickLower = mintEvent.tickLower;
|
||||||
tickUpper: mintEvent.tickUpper
|
mint.tickUpper = mintEvent.tickUpper;
|
||||||
});
|
|
||||||
|
|
||||||
// Tick entities.
|
// Tick entities.
|
||||||
const lowerTickIdx = mintEvent.tickLower;
|
const lowerTickIdx = mintEvent.tickLower;
|
||||||
@ -380,8 +402,16 @@ export class Indexer {
|
|||||||
const lowerTickId = poolAddress + '#' + mintEvent.tickLower.toString();
|
const lowerTickId = poolAddress + '#' + mintEvent.tickLower.toString();
|
||||||
const upperTickId = poolAddress + '#' + mintEvent.tickUpper.toString();
|
const upperTickId = poolAddress + '#' + mintEvent.tickUpper.toString();
|
||||||
|
|
||||||
const lowerTick = await loadTick(this._db, lowerTickId, BigInt(lowerTickIdx), pool, blockNumber);
|
let lowerTick = await this._db.getTick({ id: lowerTickId, blockNumber });
|
||||||
const upperTick = await loadTick(this._db, upperTickId, BigInt(upperTickIdx), pool, 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);
|
const amount = BigInt(mintEvent.amount);
|
||||||
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) + amount;
|
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) + amount;
|
||||||
@ -392,36 +422,38 @@ export class Indexer {
|
|||||||
// TODO: Update Tick's volume, fees, and liquidity provider count.
|
// 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.
|
// Computing these on the tick level requires reimplementing some of the swapping code from v3-core.
|
||||||
|
|
||||||
await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updateUniswapDayData(this._db, { block, contractAddress });
|
||||||
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updatePoolDayData(this._db, { block, contractAddress });
|
||||||
await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updatePoolHourData(this._db, { block, contractAddress });
|
||||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenDayData(this._db, token0, { block });
|
||||||
await updateTokenDayData(this._db, token1, { blockNumber, blockTimestamp });
|
await updateTokenDayData(this._db, token1, { block });
|
||||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenHourData(this._db, token0, { block });
|
||||||
await updateTokenHourData(this._db, token1, { blockNumber, blockTimestamp });
|
await updateTokenHourData(this._db, token1, { block });
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._db.saveToken(token0, blockNumber),
|
this._db.saveToken(token0, block),
|
||||||
this._db.saveToken(token1, blockNumber)
|
this._db.saveToken(token1, block)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this._db.savePool(pool, blockNumber);
|
await this._db.savePool(pool, block);
|
||||||
await this._db.saveFactory(factory, blockNumber);
|
await this._db.saveFactory(factory, block);
|
||||||
|
await this._db.saveMint(mint, block);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
await this._db.saveTick(lowerTick, blockNumber),
|
await this._db.saveTick(lowerTick, block),
|
||||||
await this._db.saveTick(upperTick, blockNumber)
|
await this._db.saveTick(upperTick, block)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Skipping update inner tick vars and tick day data as they are not queried.
|
// Skipping update inner tick vars and tick day data as they are not queried.
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleBurn (block: Block, contractAddress: string, tx: Transaction, burnEvent: BurnEvent): Promise<void> {
|
async _handleBurn (block: Block, contractAddress: string, tx: Transaction, burnEvent: BurnEvent): Promise<void> {
|
||||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
const { number: blockNumber } = block;
|
||||||
const { hash: txHash } = tx;
|
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
assert(bundle);
|
||||||
const poolAddress = contractAddress;
|
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.
|
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||||
// Currently fetching first factory in database as only one exists.
|
// Currently fetching first factory in database as only one exists.
|
||||||
@ -479,74 +511,75 @@ export class Indexer {
|
|||||||
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
factory.totalValueLockedUSD = factory.totalValueLockedETH.times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
// Burn entity.
|
// Burn entity.
|
||||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
const transaction = await loadTransaction(this._db, { block, tx });
|
||||||
|
|
||||||
await this._db.loadBurn({
|
const burn = new Burn();
|
||||||
id: transaction.id + '#' + pool.txCount.toString(),
|
burn.id = transaction.id + '#' + pool.txCount.toString();
|
||||||
blockNumber,
|
burn.transaction = transaction;
|
||||||
transaction,
|
burn.timestamp = transaction.timestamp;
|
||||||
timestamp: transaction.timestamp,
|
burn.pool = pool;
|
||||||
pool,
|
burn.token0 = pool.token0;
|
||||||
token0: pool.token0,
|
burn.token1 = pool.token1;
|
||||||
token1: pool.token1,
|
burn.owner = burnEvent.owner;
|
||||||
owner: burnEvent.owner,
|
|
||||||
|
|
||||||
// TODO: Assign origin with Transaction from address.
|
// TODO: Assign origin with Transaction from address.
|
||||||
// origin: event.transaction.from
|
// origin: event.transaction.from
|
||||||
|
|
||||||
amount: burnEvent.amount,
|
burn.amount = burnEvent.amount;
|
||||||
amount0,
|
burn.amount0 = amount0;
|
||||||
amount1,
|
burn.amount1 = amount1;
|
||||||
amountUSD,
|
burn.amountUSD = amountUSD;
|
||||||
tickLower: burnEvent.tickLower,
|
burn.tickLower = burnEvent.tickLower;
|
||||||
tickUpper: burnEvent.tickUpper
|
burn.tickUpper = burnEvent.tickUpper;
|
||||||
});
|
|
||||||
|
|
||||||
// Tick entities.
|
// Tick entities.
|
||||||
const lowerTickId = poolAddress + '#' + (burnEvent.tickLower).toString();
|
const lowerTickId = poolAddress + '#' + (burnEvent.tickLower).toString();
|
||||||
const upperTickId = poolAddress + '#' + (burnEvent.tickUpper).toString();
|
const upperTickId = poolAddress + '#' + (burnEvent.tickUpper).toString();
|
||||||
const lowerTick = await this._db.loadTick({ id: lowerTickId, blockNumber });
|
const lowerTick = await this._db.getTick({ id: lowerTickId, blockNumber });
|
||||||
const upperTick = await this._db.loadTick({ id: upperTickId, blockNumber });
|
const upperTick = await this._db.getTick({ id: upperTickId, blockNumber });
|
||||||
|
assert(lowerTick && upperTick);
|
||||||
const amount = BigInt(burnEvent.amount);
|
const amount = BigInt(burnEvent.amount);
|
||||||
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) - amount;
|
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) - amount;
|
||||||
lowerTick.liquidityNet = BigInt(lowerTick.liquidityNet) - amount;
|
lowerTick.liquidityNet = BigInt(lowerTick.liquidityNet) - amount;
|
||||||
upperTick.liquidityGross = BigInt(upperTick.liquidityGross) - amount;
|
upperTick.liquidityGross = BigInt(upperTick.liquidityGross) - amount;
|
||||||
upperTick.liquidityNet = BigInt(upperTick.liquidityNet) + amount;
|
upperTick.liquidityNet = BigInt(upperTick.liquidityNet) + amount;
|
||||||
|
|
||||||
await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updateUniswapDayData(this._db, { block, contractAddress });
|
||||||
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updatePoolDayData(this._db, { block, contractAddress });
|
||||||
await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updatePoolHourData(this._db, { block, contractAddress });
|
||||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenDayData(this._db, token0, { block });
|
||||||
await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenDayData(this._db, token0, { block });
|
||||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenHourData(this._db, token0, { block });
|
||||||
await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
await updateTokenHourData(this._db, token0, { block });
|
||||||
|
|
||||||
// Skipping update Tick fee and Tick day data as they are not queried.
|
// Skipping update Tick fee and Tick day data as they are not queried.
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
await this._db.saveTick(lowerTick, blockNumber),
|
await this._db.saveTick(lowerTick, block),
|
||||||
await this._db.saveTick(upperTick, blockNumber)
|
await this._db.saveTick(upperTick, block)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this._db.saveToken(token0, blockNumber),
|
this._db.saveToken(token0, block),
|
||||||
this._db.saveToken(token1, blockNumber)
|
this._db.saveToken(token1, block)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
await this._db.savePool(pool, blockNumber);
|
await this._db.savePool(pool, block);
|
||||||
await this._db.saveFactory(factory, blockNumber);
|
await this._db.saveFactory(factory, block);
|
||||||
|
await this._db.saveBurn(burn, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleSwap (block: Block, contractAddress: string, tx: Transaction, swapEvent: SwapEvent): Promise<void> {
|
async _handleSwap (block: Block, contractAddress: string, tx: Transaction, swapEvent: SwapEvent): Promise<void> {
|
||||||
const { number: blockNumber, timestamp: blockTimestamp } = block;
|
const { number: blockNumber } = block;
|
||||||
const { hash: txHash } = tx;
|
const bundle = await this._db.getBundle({ id: '1', blockNumber });
|
||||||
const bundle = await this._db.loadBundle({ id: '1', blockNumber });
|
assert(bundle);
|
||||||
|
|
||||||
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||||
// Currently fetching first factory in database as only one exists.
|
// Currently fetching first factory in database as only one exists.
|
||||||
const [factory] = await this._db.getFactories({ blockNumber }, { limit: 1 });
|
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.
|
// Hot fix for bad pricing.
|
||||||
if (pool.id === '0x9663f2ca0454accad3e094448ea6f77443880454') {
|
if (pool.id === '0x9663f2ca0454accad3e094448ea6f77443880454') {
|
||||||
@ -637,11 +670,11 @@ export class Indexer {
|
|||||||
const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token);
|
const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token);
|
||||||
pool.token0Price = prices[0];
|
pool.token0Price = prices[0];
|
||||||
pool.token1Price = prices[1];
|
pool.token1Price = prices[1];
|
||||||
this._db.savePool(pool, blockNumber);
|
this._db.savePool(pool, block);
|
||||||
|
|
||||||
// Update USD pricing.
|
// Update USD pricing.
|
||||||
bundle.ethPriceUSD = await getEthPriceInUSD(this._db);
|
bundle.ethPriceUSD = await getEthPriceInUSD(this._db);
|
||||||
this._db.saveBundle(bundle, blockNumber);
|
this._db.saveBundle(bundle, block);
|
||||||
token0.derivedETH = await findEthPerToken(token0);
|
token0.derivedETH = await findEthPerToken(token0);
|
||||||
token1.derivedETH = await findEthPerToken(token1);
|
token1.derivedETH = await findEthPerToken(token1);
|
||||||
|
|
||||||
@ -661,39 +694,37 @@ export class Indexer {
|
|||||||
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH).times(bundle.ethPriceUSD);
|
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH).times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
// Create Swap event
|
// Create Swap event
|
||||||
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
const transaction = await loadTransaction(this._db, { block, tx });
|
||||||
|
|
||||||
await this._db.loadSwap({
|
const swap = new Swap();
|
||||||
id: transaction.id + '#' + pool.txCount.toString(),
|
swap.id = transaction.id + '#' + pool.txCount.toString();
|
||||||
blockNumber,
|
swap.transaction = transaction;
|
||||||
transaction,
|
swap.timestamp = transaction.timestamp;
|
||||||
timestamp: transaction.timestamp,
|
swap.pool = pool;
|
||||||
pool,
|
swap.token0 = pool.token0;
|
||||||
token0: pool.token0,
|
swap.token1 = pool.token1;
|
||||||
token1: pool.token1,
|
swap.sender = swapEvent.sender;
|
||||||
sender: swapEvent.sender,
|
|
||||||
|
|
||||||
// TODO: Assign origin with Transaction from address.
|
// TODO: Assign origin with Transaction from address.
|
||||||
// origin: event.transaction.from
|
// origin: event.transaction.from
|
||||||
|
|
||||||
recipient: swapEvent.recipient,
|
swap.recipient = swapEvent.recipient;
|
||||||
amount0: amount0,
|
swap.amount0 = amount0;
|
||||||
amount1: amount1,
|
swap.amount1 = amount1;
|
||||||
amountUSD: amountTotalUSDTracked,
|
swap.amountUSD = amountTotalUSDTracked;
|
||||||
tick: BigInt(swapEvent.tick),
|
swap.tick = BigInt(swapEvent.tick);
|
||||||
sqrtPriceX96: swapEvent.sqrtPriceX96
|
swap.sqrtPriceX96 = swapEvent.sqrtPriceX96;
|
||||||
});
|
|
||||||
|
|
||||||
// Skipping update pool fee growth as they are not queried.
|
// Skipping update pool fee growth as they are not queried.
|
||||||
|
|
||||||
// Interval data.
|
// Interval data.
|
||||||
const uniswapDayData = await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
const uniswapDayData = await updateUniswapDayData(this._db, { block, contractAddress });
|
||||||
const poolDayData = await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
const poolDayData = await updatePoolDayData(this._db, { block, contractAddress });
|
||||||
const poolHourData = await updatePoolHourData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
const poolHourData = await updatePoolHourData(this._db, { block, contractAddress });
|
||||||
const token0DayData = await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
const token0DayData = await updateTokenDayData(this._db, token0, { block });
|
||||||
const token1DayData = await updateTokenDayData(this._db, token0, { blockNumber, blockTimestamp });
|
const token1DayData = await updateTokenDayData(this._db, token0, { block });
|
||||||
const token0HourData = await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
const token0HourData = await updateTokenHourData(this._db, token0, { block });
|
||||||
const token1HourData = await updateTokenHourData(this._db, token0, { blockNumber, blockTimestamp });
|
const token1HourData = await updateTokenHourData(this._db, token0, { block });
|
||||||
|
|
||||||
// Update volume metrics.
|
// Update volume metrics.
|
||||||
uniswapDayData.volumeETH = uniswapDayData.volumeETH.plus(amountTotalETHTracked);
|
uniswapDayData.volumeETH = uniswapDayData.volumeETH.plus(amountTotalETHTracked);
|
||||||
@ -730,20 +761,20 @@ export class Indexer {
|
|||||||
token1HourData.untrackedVolumeUSD = token1HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked);
|
token1HourData.untrackedVolumeUSD = token1HourData.untrackedVolumeUSD.plus(amountTotalUSDTracked);
|
||||||
token1HourData.feesUSD = token1HourData.feesUSD.plus(feesUSD);
|
token1HourData.feesUSD = token1HourData.feesUSD.plus(feesUSD);
|
||||||
|
|
||||||
this._db.saveTokenDayData(token0DayData, blockNumber);
|
await this._db.saveSwap(swap, block);
|
||||||
this._db.saveTokenDayData(token1DayData, blockNumber);
|
await this._db.saveTokenDayData(token0DayData, block);
|
||||||
this._db.saveUniswapDayData(uniswapDayData, blockNumber);
|
await this._db.saveTokenDayData(token1DayData, block);
|
||||||
this._db.savePoolDayData(poolDayData, blockNumber);
|
await this._db.saveUniswapDayData(uniswapDayData, block);
|
||||||
this._db.saveFactory(factory, blockNumber);
|
await this._db.savePoolDayData(poolDayData, block);
|
||||||
this._db.savePool(pool, blockNumber);
|
await this._db.saveFactory(factory, block);
|
||||||
this._db.saveToken(token0, blockNumber);
|
await this._db.savePool(pool, block);
|
||||||
this._db.saveToken(token1, blockNumber);
|
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.
|
// 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> {
|
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));
|
const position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||||
|
|
||||||
// position was not able to be fetched.
|
// 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._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);
|
await this._savePositionSnapshot(position, block, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleDecreaseLiquidity (block: Block, contractAddress: string, tx: Transaction, event: DecreaseLiquidityEvent): Promise<void> {
|
async _handleDecreaseLiquidity (block: Block, contractAddress: string, tx: Transaction, event: DecreaseLiquidityEvent): Promise<void> {
|
||||||
const { number: blockNumber } = block;
|
let position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||||
const position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
|
||||||
|
|
||||||
// Position was not able to be fetched.
|
// Position was not able to be fetched.
|
||||||
if (position == null) {
|
if (position == null) {
|
||||||
@ -796,15 +826,14 @@ export class Indexer {
|
|||||||
position.depositedToken0 = position.depositedToken0.plus(amount0);
|
position.depositedToken0 = position.depositedToken0.plus(amount0);
|
||||||
position.depositedToken1 = position.depositedToken1.plus(amount1);
|
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);
|
await this._savePositionSnapshot(position, block, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _handleCollect (block: Block, contractAddress: string, tx: Transaction, event: CollectEvent): Promise<void> {
|
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));
|
let position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||||
|
|
||||||
// Position was not able to be fetched.
|
// Position was not able to be fetched.
|
||||||
@ -826,7 +855,7 @@ export class Indexer {
|
|||||||
|
|
||||||
position = 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);
|
await this._savePositionSnapshot(position, block, tx);
|
||||||
}
|
}
|
||||||
@ -839,14 +868,13 @@ export class Indexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
position.owner = event.to;
|
position.owner = event.to;
|
||||||
await this._db.savePosition(position, block.number);
|
await this._db.savePosition(position, block);
|
||||||
|
|
||||||
await this._savePositionSnapshot(position, block, tx);
|
await this._savePositionSnapshot(position, block, tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getPosition (block: Block, contractAddress: string, tx: Transaction, tokenId: bigint): Promise<Position | null> {
|
async _getPosition (block: Block, contractAddress: string, tx: Transaction, tokenId: bigint): Promise<Position | null> {
|
||||||
const { number: blockNumber, hash: blockHash, timestamp: blockTimestamp } = block;
|
const { number: blockNumber, hash: blockHash } = block;
|
||||||
const { hash: txHash } = tx;
|
|
||||||
let position = await this._db.getPosition({ id: tokenId.toString(), blockNumber });
|
let position = await this._db.getPosition({ id: tokenId.toString(), blockNumber });
|
||||||
|
|
||||||
if (!position) {
|
if (!position) {
|
||||||
@ -861,31 +889,36 @@ export class Indexer {
|
|||||||
|
|
||||||
const { pool: poolAddress } = await this._uniClient.getPool(blockHash, token0Address, token1Address, fee);
|
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 });
|
const pool = await this._db.getPool({ id: poolAddress, blockNumber });
|
||||||
|
assert(pool);
|
||||||
|
position.pool = pool;
|
||||||
|
|
||||||
const [token0, token1] = await Promise.all([
|
const [token0, token1] = await Promise.all([
|
||||||
this._db.getToken({ id: token0Address, blockNumber }),
|
this._db.getToken({ id: token0Address, blockNumber }),
|
||||||
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([
|
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.tickLower.toString()), blockNumber }),
|
||||||
this._db.getTick({ id: poolAddress.concat('#').concat(nfpmPosition.tickUpper.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({
|
const transaction = await loadTransaction(this._db, { block, tx });
|
||||||
id: tokenId.toString(),
|
position.transaction = transaction;
|
||||||
blockNumber,
|
|
||||||
pool,
|
position.feeGrowthInside0LastX128 = BigInt(nfpmPosition.feeGrowthInside0LastX128.toString());
|
||||||
token0,
|
position.feeGrowthInside1LastX128 = BigInt(nfpmPosition.feeGrowthInside1LastX128.toString());
|
||||||
token1,
|
|
||||||
tickLower,
|
position = await this._db.savePosition(position, block);
|
||||||
tickUpper,
|
|
||||||
transaction,
|
|
||||||
feeGrowthInside0LastX128: BigInt(nfpmPosition.feeGrowthInside0LastX128.toString()),
|
|
||||||
feeGrowthInside1LastX128: BigInt(nfpmPosition.feeGrowthInside1LastX128.toString())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -904,25 +937,24 @@ export class Indexer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _savePositionSnapshot (position: Position, block: Block, tx: Transaction): Promise<void> {
|
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({
|
await this._db.savePositionSnapshot(positionSnapshot, block);
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
import { BigNumber } from 'ethers';
|
import { BigNumber } from 'ethers';
|
||||||
|
|
||||||
import { Transaction } from '../entity/Transaction';
|
import { Transaction as TransactionEntity } from '../entity/Transaction';
|
||||||
import { Database } from '../database';
|
import { Database } from '../database';
|
||||||
|
import { Block, Transaction } from '../events';
|
||||||
|
|
||||||
export const exponentToBigDecimal = (decimals: bigint): Decimal => {
|
export const exponentToBigDecimal = (decimals: bigint): Decimal => {
|
||||||
let bd = new Decimal(1);
|
let bd = new Decimal(1);
|
||||||
@ -22,19 +23,19 @@ export const convertTokenToDecimal = (tokenAmount: bigint, exchangeDecimals: big
|
|||||||
return (new Decimal(tokenAmount.toString())).div(exponentToBigDecimal(exchangeDecimals));
|
return (new Decimal(tokenAmount.toString())).div(exponentToBigDecimal(exchangeDecimals));
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadTransaction = async (db: Database, event: { txHash: string, blockNumber: number, blockTimestamp: number }): Promise<Transaction> => {
|
export const loadTransaction = async (db: Database, event: { block: Block, tx: Transaction }): Promise<TransactionEntity> => {
|
||||||
const { txHash, blockNumber, blockTimestamp } = event;
|
const { tx, block } = event;
|
||||||
|
let transaction = await db.getTransaction({ id: tx.hash, blockNumber: block.number });
|
||||||
|
|
||||||
const transaction = await db.loadTransaction({
|
if (!transaction) {
|
||||||
id: txHash,
|
transaction = new TransactionEntity();
|
||||||
blockNumber,
|
transaction.id = tx.hash;
|
||||||
timestamp: BigInt(blockTimestamp)
|
}
|
||||||
});
|
|
||||||
|
|
||||||
transaction.blockNumber = blockNumber;
|
transaction.blockNumber = block.number;
|
||||||
transaction.timestamp = BigInt(blockTimestamp);
|
transaction.timestamp = BigInt(block.timestamp);
|
||||||
|
|
||||||
return db.saveTransaction(transaction, blockNumber);
|
return db.saveTransaction(transaction, block);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return 0 if denominator is 0 in division.
|
// Return 0 if denominator is 0 in division.
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import assert from 'assert';
|
||||||
import { BigNumber } from 'ethers';
|
import { BigNumber } from 'ethers';
|
||||||
|
|
||||||
import { Database } from '../database';
|
import { Database } from '../database';
|
||||||
@ -7,56 +8,63 @@ import { Token } from '../entity/Token';
|
|||||||
import { TokenDayData } from '../entity/TokenDayData';
|
import { TokenDayData } from '../entity/TokenDayData';
|
||||||
import { TokenHourData } from '../entity/TokenHourData';
|
import { TokenHourData } from '../entity/TokenHourData';
|
||||||
import { UniswapDayData } from '../entity/UniswapDayData';
|
import { UniswapDayData } from '../entity/UniswapDayData';
|
||||||
|
import { Block } from '../events';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tracks global aggregate data over daily windows.
|
* Tracks global aggregate data over daily windows.
|
||||||
* @param db
|
* @param db
|
||||||
* @param event
|
* @param event
|
||||||
*/
|
*/
|
||||||
export const updateUniswapDayData = async (db: Database, event: { contractAddress: string, blockNumber: number, blockTimestamp: number }): Promise<UniswapDayData> => {
|
export const updateUniswapDayData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<UniswapDayData> => {
|
||||||
const { blockNumber, blockTimestamp } = event;
|
const { block } = event;
|
||||||
|
|
||||||
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
// TODO: In subgraph factory is fetched by hardcoded factory address.
|
||||||
// Currently fetching first factory in database as only one exists.
|
// 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 dayStartTimestamp = dayID * 86400;
|
||||||
|
|
||||||
const uniswapDayData = await db.loadUniswapDayData({
|
let uniswapDayData = await db.getUniswapDayData({ id: dayID.toString(), blockNumber: block.number });
|
||||||
id: dayID.toString(),
|
|
||||||
blockNumber,
|
if (!uniswapDayData) {
|
||||||
date: dayStartTimestamp,
|
uniswapDayData = new UniswapDayData();
|
||||||
tvlUSD: factory.totalValueLockedUSD,
|
uniswapDayData.id = dayID.toString();
|
||||||
txCount: factory.txCount
|
uniswapDayData.date = dayStartTimestamp;
|
||||||
});
|
uniswapDayData.tvlUSD = factory.totalValueLockedUSD;
|
||||||
|
uniswapDayData.txCount = factory.txCount;
|
||||||
|
}
|
||||||
|
|
||||||
uniswapDayData.tvlUSD = factory.totalValueLockedUSD;
|
uniswapDayData.tvlUSD = factory.totalValueLockedUSD;
|
||||||
uniswapDayData.txCount = factory.txCount;
|
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> => {
|
export const updatePoolDayData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<PoolDayData> => {
|
||||||
const { contractAddress, blockNumber, blockTimestamp } = event;
|
const { contractAddress, block } = event;
|
||||||
const dayID = Math.floor(blockTimestamp / 86400);
|
const dayID = Math.floor(block.timestamp / 86400);
|
||||||
const dayStartTimestamp = dayID * 86400;
|
const dayStartTimestamp = dayID * 86400;
|
||||||
|
|
||||||
const dayPoolID = contractAddress
|
const dayPoolID = contractAddress
|
||||||
.concat('-')
|
.concat('-')
|
||||||
.concat(dayID.toString());
|
.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({
|
let poolDayData = await db.getPoolDayData({ id: dayPoolID, blockNumber: block.number });
|
||||||
id: dayPoolID,
|
|
||||||
blockNumber,
|
if (!poolDayData) {
|
||||||
date: dayStartTimestamp,
|
poolDayData = new PoolDayData();
|
||||||
pool: pool,
|
poolDayData.id = dayPoolID;
|
||||||
open: pool.token0Price,
|
poolDayData.date = dayStartTimestamp;
|
||||||
high: pool.token0Price,
|
poolDayData.pool = pool;
|
||||||
low: pool.token0Price,
|
poolDayData.open = pool.token0Price;
|
||||||
close: 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)) {
|
if (Number(pool.token0Price) > Number(poolDayData.high)) {
|
||||||
poolDayData.high = pool.token0Price;
|
poolDayData.high = pool.token0Price;
|
||||||
@ -75,32 +83,36 @@ export const updatePoolDayData = async (db: Database, event: { contractAddress:
|
|||||||
poolDayData.tick = pool.tick;
|
poolDayData.tick = pool.tick;
|
||||||
poolDayData.tvlUSD = pool.totalValueLockedUSD;
|
poolDayData.tvlUSD = pool.totalValueLockedUSD;
|
||||||
poolDayData.txCount = BigInt(BigNumber.from(poolDayData.txCount).add(1).toHexString());
|
poolDayData.txCount = BigInt(BigNumber.from(poolDayData.txCount).add(1).toHexString());
|
||||||
poolDayData = await db.savePoolDayData(poolDayData, blockNumber);
|
poolDayData = await db.savePoolDayData(poolDayData, block);
|
||||||
|
|
||||||
return poolDayData;
|
return poolDayData;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updatePoolHourData = async (db: Database, event: { contractAddress: string, blockNumber: number, blockTimestamp: number }): Promise<PoolHourData> => {
|
export const updatePoolHourData = async (db: Database, event: { contractAddress: string, block: Block }): Promise<PoolHourData> => {
|
||||||
const { contractAddress, blockNumber, blockTimestamp } = event;
|
const { contractAddress, block } = event;
|
||||||
const hourIndex = Math.floor(blockTimestamp / 3600); // Get unique hour within unix history.
|
const hourIndex = Math.floor(block.timestamp / 3600); // Get unique hour within unix history.
|
||||||
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
||||||
|
|
||||||
const hourPoolID = contractAddress
|
const hourPoolID = contractAddress
|
||||||
.concat('-')
|
.concat('-')
|
||||||
.concat(hourIndex.toString());
|
.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({
|
let poolHourData = await db.getPoolHourData({ id: hourPoolID, blockNumber: block.number });
|
||||||
id: hourPoolID,
|
|
||||||
blockNumber,
|
if (!poolHourData) {
|
||||||
periodStartUnix: hourStartUnix,
|
poolHourData = new PoolHourData();
|
||||||
pool: pool,
|
poolHourData.id = hourPoolID;
|
||||||
open: pool.token0Price,
|
poolHourData.periodStartUnix = hourStartUnix;
|
||||||
high: pool.token0Price,
|
poolHourData.pool = pool;
|
||||||
low: pool.token0Price,
|
poolHourData.open = pool.token0Price;
|
||||||
close: 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)) {
|
if (Number(pool.token0Price) > Number(poolHourData.high)) {
|
||||||
poolHourData.high = pool.token0Price;
|
poolHourData.high = pool.token0Price;
|
||||||
@ -119,15 +131,16 @@ export const updatePoolHourData = async (db: Database, event: { contractAddress:
|
|||||||
poolHourData.tick = pool.tick;
|
poolHourData.tick = pool.tick;
|
||||||
poolHourData.tvlUSD = pool.totalValueLockedUSD;
|
poolHourData.tvlUSD = pool.totalValueLockedUSD;
|
||||||
poolHourData.txCount = BigInt(BigNumber.from(poolHourData.txCount).add(1).toHexString());
|
poolHourData.txCount = BigInt(BigNumber.from(poolHourData.txCount).add(1).toHexString());
|
||||||
poolHourData = await db.savePoolHourData(poolHourData, blockNumber);
|
poolHourData = await db.savePoolHourData(poolHourData, block);
|
||||||
|
|
||||||
return poolHourData;
|
return poolHourData;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateTokenDayData = async (db: Database, token: Token, event: { blockNumber: number, blockTimestamp: number }): Promise<TokenDayData> => {
|
export const updateTokenDayData = async (db: Database, token: Token, event: { block: Block }): Promise<TokenDayData> => {
|
||||||
const { blockNumber, blockTimestamp } = event;
|
const { block } = event;
|
||||||
const bundle = await db.loadBundle({ id: '1', blockNumber });
|
const bundle = await db.getBundle({ id: '1', blockNumber: block.number });
|
||||||
const dayID = Math.floor(blockTimestamp / 86400);
|
assert(bundle);
|
||||||
|
const dayID = Math.floor(block.timestamp / 86400);
|
||||||
const dayStartTimestamp = dayID * 86400;
|
const dayStartTimestamp = dayID * 86400;
|
||||||
|
|
||||||
const tokenDayID = token.id
|
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 tokenPrice = token.derivedETH.times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
const tokenDayData = await db.loadTokenDayData({
|
let tokenDayData = await db.getTokenDayData({ id: tokenDayID, blockNumber: block.number });
|
||||||
id: tokenDayID,
|
|
||||||
blockNumber,
|
if (!tokenDayData) {
|
||||||
date: dayStartTimestamp,
|
tokenDayData = new TokenDayData();
|
||||||
token,
|
tokenDayData.id = tokenDayID;
|
||||||
open: tokenPrice,
|
tokenDayData.date = dayStartTimestamp;
|
||||||
high: tokenPrice,
|
tokenDayData.token = token;
|
||||||
low: tokenPrice,
|
tokenDayData.open = tokenPrice;
|
||||||
close: tokenPrice,
|
tokenDayData.high = tokenPrice;
|
||||||
priceUSD: token.derivedETH.times(bundle.ethPriceUSD),
|
tokenDayData.low = tokenPrice;
|
||||||
totalValueLocked: token.totalValueLocked,
|
tokenDayData.close = tokenPrice;
|
||||||
totalValueLockedUSD: token.totalValueLockedUSD
|
tokenDayData.priceUSD = token.derivedETH.times(bundle.ethPriceUSD);
|
||||||
});
|
tokenDayData.totalValueLocked = token.totalValueLocked;
|
||||||
|
tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenPrice.gt(tokenDayData.high)) {
|
if (tokenPrice.gt(tokenDayData.high)) {
|
||||||
tokenDayData.high = tokenPrice;
|
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.priceUSD = token.derivedETH.times(bundle.ethPriceUSD);
|
||||||
tokenDayData.totalValueLocked = token.totalValueLocked;
|
tokenDayData.totalValueLocked = token.totalValueLocked;
|
||||||
tokenDayData.totalValueLockedUSD = token.totalValueLockedUSD;
|
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> => {
|
export const updateTokenHourData = async (db: Database, token: Token, event: { block: Block }): Promise<TokenHourData> => {
|
||||||
const { blockNumber, blockTimestamp } = event;
|
const { block } = event;
|
||||||
const bundle = await db.loadBundle({ id: '1', blockNumber });
|
const bundle = await db.getBundle({ id: '1', blockNumber: block.number });
|
||||||
const hourIndex = Math.floor(blockTimestamp / 3600); // Get unique hour within unix history.
|
assert(bundle);
|
||||||
|
const hourIndex = Math.floor(block.timestamp / 3600); // Get unique hour within unix history.
|
||||||
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
const hourStartUnix = hourIndex * 3600; // Want the rounded effect.
|
||||||
|
|
||||||
const tokenHourID = token.id
|
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 tokenPrice = token.derivedETH.times(bundle.ethPriceUSD);
|
||||||
|
|
||||||
const tokenHourData = await db.loadTokenHourData({
|
let tokenHourData = await db.getTokenHourData({ id: tokenHourID, blockNumber: block.number });
|
||||||
id: tokenHourID,
|
|
||||||
blockNumber,
|
if (!tokenHourData) {
|
||||||
periodStartUnix: hourStartUnix,
|
tokenHourData = new TokenHourData();
|
||||||
token: token,
|
tokenHourData.id = tokenHourID;
|
||||||
open: tokenPrice,
|
tokenHourData.periodStartUnix = hourStartUnix;
|
||||||
high: tokenPrice,
|
tokenHourData.token = token;
|
||||||
low: tokenPrice,
|
tokenHourData.open = tokenPrice;
|
||||||
close: tokenPrice,
|
tokenHourData.high = tokenPrice;
|
||||||
priceUSD: tokenPrice,
|
tokenHourData.low = tokenPrice;
|
||||||
totalValueLocked: token.totalValueLocked,
|
tokenHourData.close = tokenPrice;
|
||||||
totalValueLockedUSD: token.totalValueLockedUSD
|
tokenHourData.priceUSD = tokenPrice;
|
||||||
});
|
tokenHourData.totalValueLocked = token.totalValueLocked;
|
||||||
|
tokenHourData.totalValueLockedUSD = token.totalValueLockedUSD;
|
||||||
|
}
|
||||||
|
|
||||||
if (tokenPrice.gt(tokenHourData.high)) {
|
if (tokenPrice.gt(tokenHourData.high)) {
|
||||||
tokenHourData.high = tokenPrice;
|
tokenHourData.high = tokenPrice;
|
||||||
@ -203,5 +221,5 @@ export const updateTokenHourData = async (db: Database, token: Token, event: { b
|
|||||||
tokenHourData.priceUSD = tokenPrice;
|
tokenHourData.priceUSD = tokenPrice;
|
||||||
tokenHourData.totalValueLocked = token.totalValueLocked;
|
tokenHourData.totalValueLocked = token.totalValueLocked;
|
||||||
tokenHourData.totalValueLockedUSD = token.totalValueLockedUSD;
|
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 Decimal from 'decimal.js';
|
||||||
import { BigNumber } from 'ethers';
|
import { BigNumber } from 'ethers';
|
||||||
|
|
||||||
@ -125,7 +126,8 @@ export const getTrackedAmountUSD = async (
|
|||||||
tokenAmount1: Decimal,
|
tokenAmount1: Decimal,
|
||||||
token1: Token
|
token1: Token
|
||||||
): Promise<Decimal> => {
|
): 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 price0USD = token0.derivedETH.times(bundle.ethPriceUSD);
|
||||||
const price1USD = token1.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 { Database } from '../database';
|
||||||
import { bigDecimalExponated, safeDiv } from '.';
|
import { bigDecimalExponated, safeDiv } from '.';
|
||||||
import { Tick } from '../entity/Tick';
|
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.
|
// 1.0001^tick is token1/token0.
|
||||||
const price0 = bigDecimalExponated(new Decimal('1.0001'), tickIdx);
|
const price0 = bigDecimalExponated(new Decimal('1.0001'), tickIdx);
|
||||||
|
|
||||||
return db.loadTick({
|
tick.price0 = price0;
|
||||||
id: tickId,
|
tick.price1 = safeDiv(new Decimal(1), price0);
|
||||||
blockNumber,
|
|
||||||
tickIdx: tickIdx,
|
return db.saveTick(tick, block);
|
||||||
pool,
|
|
||||||
poolAddress: pool.id,
|
|
||||||
price0,
|
|
||||||
price1: safeDiv(new Decimal(1), price0)
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user