mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-09 21:08:06 +00:00
Handle increase liquidity event (#143)
* Implement handler for NFPM IncreaseLiquidity event. * Get contract values by querying uni-watcher. Co-authored-by: nabarun <nabarun@deepstacksoft.com>
This commit is contained in:
parent
ae13edb99a
commit
3477366458
@ -178,7 +178,7 @@ describe('Get value from storage', () => {
|
|||||||
const { storageLayout } = contracts.TestAddress;
|
const { storageLayout } = contracts.TestAddress;
|
||||||
const { value, proof: { data: proofData } } = await getStorageValue(storageLayout, getStorageAt, blockHash, testAddress.address, 'address1');
|
const { value, proof: { data: proofData } } = await getStorageValue(storageLayout, getStorageAt, blockHash, testAddress.address, 'address1');
|
||||||
expect(value).to.be.a('string');
|
expect(value).to.be.a('string');
|
||||||
expect(String(value).toLowerCase()).to.equal(address1Value);
|
expect(value).to.equal(address1Value);
|
||||||
|
|
||||||
if (isIpldGql) {
|
if (isIpldGql) {
|
||||||
assertProofData(blockHash, testAddress.address, JSON.parse(proofData));
|
assertProofData(blockHash, testAddress.address, JSON.parse(proofData));
|
||||||
|
@ -97,6 +97,10 @@ export const getValueByType = (storageValue: string, typeLabel: string): bigint
|
|||||||
return utils.toUtf8String(storageValue);
|
return utils.toUtf8String(storageValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeLabel.startsWith('address')) {
|
||||||
|
return utils.getAddress(storageValue);
|
||||||
|
}
|
||||||
|
|
||||||
return storageValue;
|
return storageValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ export const getStorageAt: GetStorageAt = async ({ blockHash, contract, slot })
|
|||||||
*/
|
*/
|
||||||
export const generateDummyAddresses = (length: number): Array<string> => {
|
export const generateDummyAddresses = (length: number): Array<string> => {
|
||||||
return Array.from({ length }, () => {
|
return Array.from({ length }, () => {
|
||||||
return ethers.utils.hexlify(ethers.utils.randomBytes(20));
|
return ethers.utils.getAddress(ethers.utils.hexlify(ethers.utils.randomBytes(20)));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ import { TokenDayData } from './entity/TokenDayData';
|
|||||||
import { TokenHourData } from './entity/TokenHourData';
|
import { TokenHourData } from './entity/TokenHourData';
|
||||||
import { Burn } from './entity/Burn';
|
import { Burn } from './entity/Burn';
|
||||||
import { Swap } from './entity/Swap';
|
import { Swap } from './entity/Swap';
|
||||||
|
import { Position } from './entity/Position';
|
||||||
|
import { PositionSnapshot } from './entity/PositionSnapshot';
|
||||||
|
|
||||||
export class Database {
|
export class Database {
|
||||||
_config: ConnectionOptions
|
_config: ConnectionOptions
|
||||||
@ -80,6 +82,44 @@ export class Database {
|
|||||||
return repo.findOne(findOptions);
|
return repo.findOne(findOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPosition ({ id, blockNumber }: DeepPartial<Position>): Promise<Position | undefined> {
|
||||||
|
const repo = this._conn.getRepository(Position);
|
||||||
|
const whereOptions: FindConditions<Position> = { id };
|
||||||
|
|
||||||
|
if (blockNumber) {
|
||||||
|
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
const findOptions: FindOneOptions<Position> = {
|
||||||
|
where: whereOptions,
|
||||||
|
relations: ['pool', 'token0', 'token1', 'tickLower', 'tickUpper', 'transaction'],
|
||||||
|
order: {
|
||||||
|
blockNumber: 'DESC'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return repo.findOne(findOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getTick ({ id, blockNumber }: DeepPartial<Tick>): Promise<Tick | undefined> {
|
||||||
|
const repo = this._conn.getRepository(Tick);
|
||||||
|
const whereOptions: FindConditions<Tick> = { id };
|
||||||
|
|
||||||
|
if (blockNumber) {
|
||||||
|
whereOptions.blockNumber = LessThanOrEqual(blockNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
const findOptions: FindOneOptions<Tick> = {
|
||||||
|
where: whereOptions,
|
||||||
|
relations: ['pool'],
|
||||||
|
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);
|
||||||
|
|
||||||
@ -438,6 +478,52 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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> {
|
async saveFactory (factory: Factory, blockNumber: number): Promise<Factory> {
|
||||||
return this._conn.transaction(async (tx) => {
|
return this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Factory);
|
const repo = tx.getRepository(Factory);
|
||||||
@ -526,6 +612,14 @@ export class Database {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async savePosition (position: Position, blockNumber: number): Promise<Position> {
|
||||||
|
return this._conn.transaction(async (tx) => {
|
||||||
|
const repo = tx.getRepository(Position);
|
||||||
|
position.blockNumber = blockNumber;
|
||||||
|
return repo.save(position);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
66
packages/uni-info-watcher/src/entity/Position.ts
Normal file
66
packages/uni-info-watcher/src/entity/Position.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
|
||||||
|
import Decimal from 'decimal.js';
|
||||||
|
import { decimalTransformer } from '@vulcanize/util';
|
||||||
|
|
||||||
|
import { Pool } from './Pool';
|
||||||
|
import { Token } from './Token';
|
||||||
|
import { Tick } from './Tick';
|
||||||
|
import { Transaction } from './Transaction';
|
||||||
|
import { ADDRESS_ZERO } from '../utils/constants';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Position {
|
||||||
|
@PrimaryColumn('varchar')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@PrimaryColumn('integer')
|
||||||
|
blockNumber!: number;
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
feeGrowthInside0LastX128!: bigint
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
feeGrowthInside1LastX128!: bigint
|
||||||
|
|
||||||
|
@Column('bigint', { default: BigInt(0) })
|
||||||
|
liquidity!: bigint
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
depositedToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
depositedToken1!: Decimal
|
||||||
|
|
||||||
|
@Column('varchar', { length: 42, default: ADDRESS_ZERO })
|
||||||
|
owner!: string
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
withdrawnToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
withdrawnToken1!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
collectedFeesToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
collectedFeesToken1!: Decimal
|
||||||
|
|
||||||
|
@ManyToOne(() => Pool)
|
||||||
|
pool!: Pool
|
||||||
|
|
||||||
|
@ManyToOne(() => Token)
|
||||||
|
token0!: Token
|
||||||
|
|
||||||
|
@ManyToOne(() => Token)
|
||||||
|
token1!: Token
|
||||||
|
|
||||||
|
@ManyToOne(() => Tick)
|
||||||
|
tickLower!: Tick
|
||||||
|
|
||||||
|
@ManyToOne(() => Tick)
|
||||||
|
tickUpper!: Tick
|
||||||
|
|
||||||
|
@ManyToOne(() => Transaction)
|
||||||
|
transaction!: Transaction
|
||||||
|
}
|
59
packages/uni-info-watcher/src/entity/PositionSnapshot.ts
Normal file
59
packages/uni-info-watcher/src/entity/PositionSnapshot.ts
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { Entity, PrimaryColumn, Column, ManyToOne } from 'typeorm';
|
||||||
|
import Decimal from 'decimal.js';
|
||||||
|
import { decimalTransformer } from '@vulcanize/util';
|
||||||
|
|
||||||
|
import { Pool } from './Pool';
|
||||||
|
import { Transaction } from './Transaction';
|
||||||
|
import { ADDRESS_ZERO } from '../utils/constants';
|
||||||
|
import { Position } from './Position';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class PositionSnapshot {
|
||||||
|
@PrimaryColumn('varchar')
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@PrimaryColumn('integer')
|
||||||
|
blockNumber!: number;
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
timestamp!: BigInt;
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
feeGrowthInside0LastX128!: bigint
|
||||||
|
|
||||||
|
@Column('bigint')
|
||||||
|
feeGrowthInside1LastX128!: bigint
|
||||||
|
|
||||||
|
@Column('bigint', { default: BigInt(0) })
|
||||||
|
liquidity!: bigint
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
depositedToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
depositedToken1!: Decimal
|
||||||
|
|
||||||
|
@Column('varchar', { length: 42, default: ADDRESS_ZERO })
|
||||||
|
owner!: string
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
withdrawnToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
withdrawnToken1!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
collectedFeesToken0!: Decimal
|
||||||
|
|
||||||
|
@Column('numeric', { default: 0, transformer: decimalTransformer })
|
||||||
|
collectedFeesToken1!: Decimal
|
||||||
|
|
||||||
|
@ManyToOne(() => Pool)
|
||||||
|
pool!: Pool
|
||||||
|
|
||||||
|
@ManyToOne(() => Position)
|
||||||
|
position!: Position
|
||||||
|
|
||||||
|
@ManyToOne(() => Transaction)
|
||||||
|
transaction!: Transaction
|
||||||
|
}
|
@ -2,7 +2,7 @@ import assert from 'assert';
|
|||||||
import debug from 'debug';
|
import debug from 'debug';
|
||||||
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';
|
||||||
import { BigNumber } from 'ethers';
|
import { BigNumber, utils } from 'ethers';
|
||||||
|
|
||||||
import { Database } from './database';
|
import { Database } from './database';
|
||||||
import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices, WHITELIST_TOKENS } from './utils/pricing';
|
import { findEthPerToken, getEthPriceInUSD, getTrackedAmountUSD, sqrtPriceX96ToTokenPrices, WHITELIST_TOKENS } from './utils/pricing';
|
||||||
@ -11,6 +11,7 @@ import { Token } from './entity/Token';
|
|||||||
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
|
import { convertTokenToDecimal, loadTransaction, safeDiv } from './utils';
|
||||||
import { loadTick } from './utils/tick';
|
import { loadTick } from './utils/tick';
|
||||||
import Decimal from 'decimal.js';
|
import Decimal from 'decimal.js';
|
||||||
|
import { Position } from './entity/Position';
|
||||||
|
|
||||||
const log = debug('vulcanize:events');
|
const log = debug('vulcanize:events');
|
||||||
|
|
||||||
@ -61,6 +62,14 @@ interface SwapEvent {
|
|||||||
tick: bigint;
|
tick: bigint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface IncreaseLiquidityEvent {
|
||||||
|
__typename: 'IncreaseLiquidityEvent';
|
||||||
|
tokenId: bigint;
|
||||||
|
liquidity: bigint;
|
||||||
|
amount0: bigint;
|
||||||
|
amount1: bigint;
|
||||||
|
}
|
||||||
|
|
||||||
interface Block {
|
interface Block {
|
||||||
number: number;
|
number: number;
|
||||||
hash: string;
|
hash: string;
|
||||||
@ -76,7 +85,7 @@ interface ResultEvent {
|
|||||||
block: Block;
|
block: Block;
|
||||||
tx: Transaction;
|
tx: Transaction;
|
||||||
contract: string;
|
contract: string;
|
||||||
event: PoolCreatedEvent | InitializeEvent | MintEvent | BurnEvent | SwapEvent;
|
event: PoolCreatedEvent | InitializeEvent | MintEvent | BurnEvent | SwapEvent | IncreaseLiquidityEvent;
|
||||||
proof: {
|
proof: {
|
||||||
data: string;
|
data: string;
|
||||||
}
|
}
|
||||||
@ -139,6 +148,11 @@ export class EventWatcher {
|
|||||||
this._handleSwap(block, contract, tx, event as SwapEvent);
|
this._handleSwap(block, contract, tx, event as SwapEvent);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'IncreaseLiquidityEvent':
|
||||||
|
log('NFPM IncreaseLiquidity event', contract);
|
||||||
|
this._handleIncreaseLiquidity(block, contract, tx, event as IncreaseLiquidityEvent);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -299,7 +313,7 @@ export class EventWatcher {
|
|||||||
BigInt(mintEvent.tickLower) <= BigInt(pool.tick) &&
|
BigInt(mintEvent.tickLower) <= BigInt(pool.tick) &&
|
||||||
BigInt(mintEvent.tickUpper) > BigInt(pool.tick)
|
BigInt(mintEvent.tickUpper) > BigInt(pool.tick)
|
||||||
) {
|
) {
|
||||||
pool.liquidity = BigInt(pool.liquidity) + mintEvent.amount;
|
pool.liquidity = BigInt(pool.liquidity) + BigInt(mintEvent.amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,14 +360,14 @@ export class EventWatcher {
|
|||||||
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, lowerTickIdx, pool, blockNumber);
|
const lowerTick = await loadTick(this._db, lowerTickId, BigInt(lowerTickIdx), pool, blockNumber);
|
||||||
const upperTick = await loadTick(this._db, upperTickId, upperTickIdx, pool, blockNumber);
|
const upperTick = await loadTick(this._db, upperTickId, BigInt(upperTickIdx), pool, blockNumber);
|
||||||
|
|
||||||
const amount = mintEvent.amount;
|
const amount = BigInt(mintEvent.amount);
|
||||||
lowerTick.liquidityGross = lowerTick.liquidityGross + amount;
|
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) + amount;
|
||||||
lowerTick.liquidityNet = lowerTick.liquidityNet + amount;
|
lowerTick.liquidityNet = BigInt(lowerTick.liquidityNet) + amount;
|
||||||
upperTick.liquidityGross = upperTick.liquidityGross + amount;
|
upperTick.liquidityGross = BigInt(upperTick.liquidityGross) + amount;
|
||||||
upperTick.liquidityNet = upperTick.liquidityNet + amount;
|
upperTick.liquidityNet = BigInt(upperTick.liquidityNet) + amount;
|
||||||
|
|
||||||
// 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.
|
||||||
@ -395,8 +409,8 @@ export class EventWatcher {
|
|||||||
|
|
||||||
const token0 = pool.token0;
|
const token0 = pool.token0;
|
||||||
const token1 = pool.token1;
|
const token1 = pool.token1;
|
||||||
const amount0 = convertTokenToDecimal(burnEvent.amount0, token0.decimals);
|
const amount0 = convertTokenToDecimal(burnEvent.amount0, BigInt(token0.decimals));
|
||||||
const amount1 = convertTokenToDecimal(burnEvent.amount1, token1.decimals);
|
const amount1 = convertTokenToDecimal(burnEvent.amount1, BigInt(token1.decimals));
|
||||||
|
|
||||||
const amountUSD = amount0
|
const amountUSD = amount0
|
||||||
.times(token0.derivedETH.times(bundle.ethPriceUSD))
|
.times(token0.derivedETH.times(bundle.ethPriceUSD))
|
||||||
@ -406,20 +420,20 @@ export class EventWatcher {
|
|||||||
factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH);
|
factory.totalValueLockedETH = factory.totalValueLockedETH.minus(pool.totalValueLockedETH);
|
||||||
|
|
||||||
// Update globals.
|
// Update globals.
|
||||||
factory.txCount = factory.txCount + BigInt(1);
|
factory.txCount = BigInt(factory.txCount) + BigInt(1);
|
||||||
|
|
||||||
// Update token0 data.
|
// Update token0 data.
|
||||||
token0.txCount = token0.txCount + BigInt(1);
|
token0.txCount = BigInt(token0.txCount) + BigInt(1);
|
||||||
token0.totalValueLocked = token0.totalValueLocked.minus(amount0);
|
token0.totalValueLocked = token0.totalValueLocked.minus(amount0);
|
||||||
token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD));
|
token0.totalValueLockedUSD = token0.totalValueLocked.times(token0.derivedETH.times(bundle.ethPriceUSD));
|
||||||
|
|
||||||
// Update token1 data.
|
// Update token1 data.
|
||||||
token1.txCount = token1.txCount + BigInt(1);
|
token1.txCount = BigInt(token1.txCount) + BigInt(1);
|
||||||
token1.totalValueLocked = token1.totalValueLocked.minus(amount1);
|
token1.totalValueLocked = token1.totalValueLocked.minus(amount1);
|
||||||
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD));
|
token1.totalValueLockedUSD = token1.totalValueLocked.times(token1.derivedETH.times(bundle.ethPriceUSD));
|
||||||
|
|
||||||
// Pool data.
|
// Pool data.
|
||||||
pool.txCount = pool.txCount + BigInt(1);
|
pool.txCount = BigInt(pool.txCount) + BigInt(1);
|
||||||
|
|
||||||
// Pools liquidity tracks the currently active liquidity given pools current tick.
|
// Pools liquidity tracks the currently active liquidity given pools current tick.
|
||||||
// We only want to update it on burn if the position being burnt includes the current tick.
|
// We only want to update it on burn if the position being burnt includes the current tick.
|
||||||
@ -473,11 +487,11 @@ export class EventWatcher {
|
|||||||
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.loadTick({ id: lowerTickId, blockNumber });
|
||||||
const upperTick = await this._db.loadTick({ id: upperTickId, blockNumber });
|
const upperTick = await this._db.loadTick({ id: upperTickId, blockNumber });
|
||||||
const amount = burnEvent.amount;
|
const amount = BigInt(burnEvent.amount);
|
||||||
lowerTick.liquidityGross = lowerTick.liquidityGross - amount;
|
lowerTick.liquidityGross = BigInt(lowerTick.liquidityGross) - amount;
|
||||||
lowerTick.liquidityNet = lowerTick.liquidityNet - amount;
|
lowerTick.liquidityNet = BigInt(lowerTick.liquidityNet) - amount;
|
||||||
upperTick.liquidityGross = upperTick.liquidityGross - amount;
|
upperTick.liquidityGross = BigInt(upperTick.liquidityGross) - amount;
|
||||||
upperTick.liquidityNet = upperTick.liquidityNet + amount;
|
upperTick.liquidityNet = BigInt(upperTick.liquidityNet) + amount;
|
||||||
|
|
||||||
await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updateUniswapDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||||
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
await updatePoolDayData(this._db, { blockNumber, contractAddress, blockTimestamp });
|
||||||
@ -527,8 +541,8 @@ export class EventWatcher {
|
|||||||
assert(token0 && token1, 'Pool tokens not found.');
|
assert(token0 && token1, 'Pool tokens not found.');
|
||||||
|
|
||||||
// Amounts - 0/1 are token deltas. Can be positive or negative.
|
// Amounts - 0/1 are token deltas. Can be positive or negative.
|
||||||
const amount0 = convertTokenToDecimal(swapEvent.amount0, token0.decimals);
|
const amount0 = convertTokenToDecimal(swapEvent.amount0, BigInt(token0.decimals));
|
||||||
const amount1 = convertTokenToDecimal(swapEvent.amount1, token1.decimals);
|
const amount1 = convertTokenToDecimal(swapEvent.amount1, BigInt(token1.decimals));
|
||||||
|
|
||||||
// Need absolute amounts for volume.
|
// Need absolute amounts for volume.
|
||||||
let amount0Abs = amount0;
|
let amount0Abs = amount0;
|
||||||
@ -557,7 +571,7 @@ export class EventWatcher {
|
|||||||
const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new Decimal('1000000'));
|
const feesUSD = amountTotalUSDTracked.times(pool.feeTier.toString()).div(new Decimal('1000000'));
|
||||||
|
|
||||||
// Global updates.
|
// Global updates.
|
||||||
factory.txCount = factory.txCount + BigInt(1);
|
factory.txCount = BigInt(factory.txCount) + BigInt(1);
|
||||||
factory.totalVolumeETH = factory.totalVolumeETH.plus(amountTotalETHTracked);
|
factory.totalVolumeETH = factory.totalVolumeETH.plus(amountTotalETHTracked);
|
||||||
factory.totalVolumeUSD = factory.totalVolumeUSD.plus(amountTotalUSDTracked);
|
factory.totalVolumeUSD = factory.totalVolumeUSD.plus(amountTotalUSDTracked);
|
||||||
factory.untrackedVolumeUSD = factory.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
factory.untrackedVolumeUSD = factory.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
||||||
@ -574,7 +588,7 @@ export class EventWatcher {
|
|||||||
pool.volumeUSD = pool.volumeUSD.plus(amountTotalUSDTracked);
|
pool.volumeUSD = pool.volumeUSD.plus(amountTotalUSDTracked);
|
||||||
pool.untrackedVolumeUSD = pool.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
pool.untrackedVolumeUSD = pool.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
||||||
pool.feesUSD = pool.feesUSD.plus(feesUSD);
|
pool.feesUSD = pool.feesUSD.plus(feesUSD);
|
||||||
pool.txCount = pool.txCount + BigInt(1);
|
pool.txCount = BigInt(pool.txCount) + BigInt(1);
|
||||||
|
|
||||||
// Update the pool with the new active liquidity, price, and tick.
|
// Update the pool with the new active liquidity, price, and tick.
|
||||||
pool.liquidity = swapEvent.liquidity;
|
pool.liquidity = swapEvent.liquidity;
|
||||||
@ -589,7 +603,7 @@ export class EventWatcher {
|
|||||||
token0.volumeUSD = token0.volumeUSD.plus(amountTotalUSDTracked);
|
token0.volumeUSD = token0.volumeUSD.plus(amountTotalUSDTracked);
|
||||||
token0.untrackedVolumeUSD = token0.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
token0.untrackedVolumeUSD = token0.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
||||||
token0.feesUSD = token0.feesUSD.plus(feesUSD);
|
token0.feesUSD = token0.feesUSD.plus(feesUSD);
|
||||||
token0.txCount = token0.txCount + BigInt(1);
|
token0.txCount = BigInt(token0.txCount) + BigInt(1);
|
||||||
|
|
||||||
// Update token1 data.
|
// Update token1 data.
|
||||||
token1.volume = token1.volume.plus(amount1Abs);
|
token1.volume = token1.volume.plus(amount1Abs);
|
||||||
@ -597,7 +611,7 @@ export class EventWatcher {
|
|||||||
token1.volumeUSD = token1.volumeUSD.plus(amountTotalUSDTracked);
|
token1.volumeUSD = token1.volumeUSD.plus(amountTotalUSDTracked);
|
||||||
token1.untrackedVolumeUSD = token1.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
token1.untrackedVolumeUSD = token1.untrackedVolumeUSD.plus(amountTotalUSDUntracked);
|
||||||
token1.feesUSD = token1.feesUSD.plus(feesUSD);
|
token1.feesUSD = token1.feesUSD.plus(feesUSD);
|
||||||
token1.txCount = token1.txCount + BigInt(1);
|
token1.txCount = BigInt(token1.txCount) + BigInt(1);
|
||||||
|
|
||||||
// Updated pool rates.
|
// Updated pool rates.
|
||||||
const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token);
|
const prices = sqrtPriceX96ToTokenPrices(pool.sqrtPrice, token0 as Token, token1 as Token);
|
||||||
@ -707,4 +721,117 @@ export class EventWatcher {
|
|||||||
|
|
||||||
// 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> {
|
||||||
|
const { number: blockNumber } = block;
|
||||||
|
const position = await this._getPosition(block, contractAddress, tx, BigInt(event.tokenId));
|
||||||
|
|
||||||
|
// position was not able to be fetched.
|
||||||
|
if (position === null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temp fix.
|
||||||
|
if (utils.getAddress(position.pool.id) === utils.getAddress('0x8fe8d9bb8eeba3ed688069c3d6b556c9ca258248')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const token0 = position.token0;
|
||||||
|
const token1 = position.token1;
|
||||||
|
|
||||||
|
const amount0 = convertTokenToDecimal(BigInt(event.amount0), BigInt(token0.decimals));
|
||||||
|
const amount1 = convertTokenToDecimal(BigInt(event.amount1), BigInt(token1.decimals));
|
||||||
|
|
||||||
|
position.liquidity = BigInt(position.liquidity) + BigInt(event.liquidity);
|
||||||
|
position.depositedToken0 = position.depositedToken0.plus(amount0);
|
||||||
|
position.depositedToken1 = position.depositedToken1.plus(amount1);
|
||||||
|
|
||||||
|
await this._updateFeeVars(position, block, contractAddress, BigInt(event.tokenId));
|
||||||
|
|
||||||
|
await this._db.savePosition(position, blockNumber);
|
||||||
|
|
||||||
|
await this._savePositionSnapshot(position, block, tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _getPosition (block: Block, contractAddress: string, tx: Transaction, tokenId: bigint): Promise<Position | null> {
|
||||||
|
const { number: blockNumber, hash: blockHash, timestamp: blockTimestamp } = block;
|
||||||
|
const { hash: txHash } = tx;
|
||||||
|
let position = await this._db.getPosition({ id: tokenId.toString(), blockNumber });
|
||||||
|
|
||||||
|
if (!position) {
|
||||||
|
const nfpmPosition = await this._uniClient.getPosition(blockHash, tokenId);
|
||||||
|
|
||||||
|
// The contract call reverts in situations where the position is minted and deleted in the same block.
|
||||||
|
// From my investigation this happens in calls from BancorSwap.
|
||||||
|
// (e.g. 0xf7867fa19aa65298fadb8d4f72d0daed5e836f3ba01f0b9b9631cdc6c36bed40)
|
||||||
|
|
||||||
|
if (nfpmPosition) {
|
||||||
|
const { token0: token0Address, token1: token1Address, fee } = await this._uniClient.poolIdToPoolKey(blockHash, nfpmPosition.poolId);
|
||||||
|
|
||||||
|
const { pool: poolAddress } = await this._uniClient.getPool(blockHash, token0Address, token1Address, fee);
|
||||||
|
|
||||||
|
const transaction = await loadTransaction(this._db, { txHash, blockNumber, blockTimestamp });
|
||||||
|
const pool = await this._db.getPool({ id: poolAddress, blockNumber });
|
||||||
|
|
||||||
|
const [token0, token1] = await Promise.all([
|
||||||
|
this._db.getToken({ id: token0Address, blockNumber }),
|
||||||
|
this._db.getToken({ id: token0Address, blockNumber })
|
||||||
|
]);
|
||||||
|
|
||||||
|
const [tickLower, tickUpper] = await Promise.all([
|
||||||
|
this._db.getTick({ id: poolAddress.concat('#').concat(nfpmPosition.tickLower.toString()), blockNumber }),
|
||||||
|
this._db.getTick({ id: poolAddress.concat('#').concat(nfpmPosition.tickUpper.toString()), blockNumber })
|
||||||
|
]);
|
||||||
|
|
||||||
|
position = await this._db.loadPosition({
|
||||||
|
id: tokenId.toString(),
|
||||||
|
blockNumber,
|
||||||
|
pool,
|
||||||
|
token0,
|
||||||
|
token1,
|
||||||
|
tickLower,
|
||||||
|
tickUpper,
|
||||||
|
transaction,
|
||||||
|
feeGrowthInside0LastX128: BigInt(nfpmPosition.feeGrowthInside0LastX128.toString()),
|
||||||
|
feeGrowthInside1LastX128: BigInt(nfpmPosition.feeGrowthInside1LastX128.toString())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return position || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async _updateFeeVars (position: Position, block: Block, contractAddress: string, tokenId: bigint): Promise<Position> {
|
||||||
|
const nfpmPosition = await this._uniClient.getPosition(block.hash, tokenId);
|
||||||
|
|
||||||
|
if (nfpmPosition) {
|
||||||
|
position.feeGrowthInside0LastX128 = BigInt(nfpmPosition.feeGrowthInside0LastX128.toString());
|
||||||
|
position.feeGrowthInside1LastX128 = BigInt(nfpmPosition.feeGrowthInside1LastX128.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 });
|
||||||
|
|
||||||
|
await this._db.loadPositionSnapshot({
|
||||||
|
id: position.id.concat('#').concat(block.number.toString()),
|
||||||
|
blockNumber: block.number,
|
||||||
|
owner: position.owner,
|
||||||
|
pool: position.pool,
|
||||||
|
position: position,
|
||||||
|
timestamp: block.timestamp,
|
||||||
|
liquidity: position.liquidity,
|
||||||
|
depositedToken0: position.depositedToken0,
|
||||||
|
depositedToken1: position.depositedToken1,
|
||||||
|
withdrawnToken0: position.withdrawnToken0,
|
||||||
|
withdrawnToken1: position.withdrawnToken1,
|
||||||
|
collectedFeesToken0: position.collectedFeesToken0,
|
||||||
|
collectedFeesToken1: position.collectedFeesToken1,
|
||||||
|
transaction,
|
||||||
|
feeGrowthInside0LastX128: position.feeGrowthInside0LastX128,
|
||||||
|
feeGrowthInside1LastX128: position.feeGrowthInside1LastX128
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
3
packages/uni-info-watcher/src/utils/constants.ts
Normal file
3
packages/uni-info-watcher/src/utils/constants.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { utils } from 'ethers';
|
||||||
|
|
||||||
|
export const ADDRESS_ZERO = utils.getAddress('0x0000000000000000000000000000000000000000');
|
@ -1,4 +1,5 @@
|
|||||||
[
|
{
|
||||||
|
"abi": [
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -292,6 +293,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
{
|
{
|
||||||
"internalType": "uint256",
|
"internalType": "uint256",
|
||||||
"name": "tokenId",
|
"name": "tokenId",
|
||||||
@ -313,6 +316,11 @@
|
|||||||
"type": "uint128"
|
"type": "uint128"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"internalType": "struct INonfungiblePositionManager.CollectParams",
|
||||||
|
"name": "params",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "collect",
|
"name": "collect",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -333,12 +341,12 @@
|
|||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
"internalType": "address",
|
"internalType": "address",
|
||||||
"name": "tokenA",
|
"name": "token0",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"internalType": "address",
|
"internalType": "address",
|
||||||
"name": "tokenB",
|
"name": "token1",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -365,6 +373,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
{
|
{
|
||||||
"internalType": "uint256",
|
"internalType": "uint256",
|
||||||
"name": "tokenId",
|
"name": "tokenId",
|
||||||
@ -391,6 +401,11 @@
|
|||||||
"type": "uint256"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"internalType": "struct INonfungiblePositionManager.DecreaseLiquidityParams",
|
||||||
|
"name": "params",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "decreaseLiquidity",
|
"name": "decreaseLiquidity",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -441,6 +456,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
{
|
{
|
||||||
"internalType": "uint256",
|
"internalType": "uint256",
|
||||||
"name": "tokenId",
|
"name": "tokenId",
|
||||||
@ -472,6 +489,11 @@
|
|||||||
"type": "uint256"
|
"type": "uint256"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"internalType": "struct INonfungiblePositionManager.IncreaseLiquidityParams",
|
||||||
|
"name": "params",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
"name": "increaseLiquidity",
|
"name": "increaseLiquidity",
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
@ -771,6 +793,13 @@
|
|||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "refundETH",
|
||||||
|
"outputs": [],
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -1190,4 +1219,482 @@
|
|||||||
"stateMutability": "payable",
|
"stateMutability": "payable",
|
||||||
"type": "receive"
|
"type": "receive"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"storageLayout": {
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"astId": 460,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_supportedInterfaces",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_mapping(t_bytes4,t_bool)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1676,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_holderTokens",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_mapping(t_address,t_struct(UintSet)4092_storage)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1678,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_tokenOwners",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "2",
|
||||||
|
"type": "t_struct(UintToAddressMap)3469_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1682,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_tokenApprovals",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "4",
|
||||||
|
"type": "t_mapping(t_uint256,t_address)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1688,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_operatorApprovals",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "5",
|
||||||
|
"type": "t_mapping(t_address,t_mapping(t_address,t_bool))"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1690,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_name",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "6",
|
||||||
|
"type": "t_string_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1692,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_symbol",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "7",
|
||||||
|
"type": "t_string_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1696,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_tokenURIs",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "8",
|
||||||
|
"type": "t_mapping(t_uint256,t_string_storage)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 1698,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_baseURI",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "9",
|
||||||
|
"type": "t_string_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7097,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_poolIds",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "10",
|
||||||
|
"type": "t_mapping(t_address,t_uint80)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7102,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_poolIdToPoolKey",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "11",
|
||||||
|
"type": "t_mapping(t_uint80,t_struct(PoolKey)16521_storage)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7107,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_positions",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "12",
|
||||||
|
"type": "t_mapping(t_uint256,t_struct(Position)7092_storage)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7111,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_nextId",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "13",
|
||||||
|
"type": "t_uint176"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7115,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_nextPoolId",
|
||||||
|
"offset": 22,
|
||||||
|
"slot": "13",
|
||||||
|
"type": "t_uint80"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": {
|
||||||
|
"t_address": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "address",
|
||||||
|
"numberOfBytes": "20"
|
||||||
|
},
|
||||||
|
"t_array(t_bytes32)dyn_storage": {
|
||||||
|
"base": "t_bytes32",
|
||||||
|
"encoding": "dynamic_array",
|
||||||
|
"label": "bytes32[]",
|
||||||
|
"numberOfBytes": "32"
|
||||||
|
},
|
||||||
|
"t_array(t_struct(MapEntry)3143_storage)dyn_storage": {
|
||||||
|
"base": "t_struct(MapEntry)3143_storage",
|
||||||
|
"encoding": "dynamic_array",
|
||||||
|
"label": "struct EnumerableMap.MapEntry[]",
|
||||||
|
"numberOfBytes": "32"
|
||||||
|
},
|
||||||
|
"t_bool": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "bool",
|
||||||
|
"numberOfBytes": "1"
|
||||||
|
},
|
||||||
|
"t_bytes32": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "bytes32",
|
||||||
|
"numberOfBytes": "32"
|
||||||
|
},
|
||||||
|
"t_bytes4": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "bytes4",
|
||||||
|
"numberOfBytes": "4"
|
||||||
|
},
|
||||||
|
"t_int24": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "int24",
|
||||||
|
"numberOfBytes": "3"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_bool)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => bool)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_bool"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_mapping(t_address,t_bool))": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => mapping(address => bool))",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_mapping(t_address,t_bool)"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_struct(UintSet)4092_storage)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => struct EnumerableSet.UintSet)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_struct(UintSet)4092_storage"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_uint80)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => uint80)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_uint80"
|
||||||
|
},
|
||||||
|
"t_mapping(t_bytes32,t_uint256)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_bytes32",
|
||||||
|
"label": "mapping(bytes32 => uint256)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_uint256"
|
||||||
|
},
|
||||||
|
"t_mapping(t_bytes4,t_bool)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_bytes4",
|
||||||
|
"label": "mapping(bytes4 => bool)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_bool"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint256,t_address)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint256",
|
||||||
|
"label": "mapping(uint256 => address)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_address"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint256,t_string_storage)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint256",
|
||||||
|
"label": "mapping(uint256 => string)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_string_storage"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint256,t_struct(Position)7092_storage)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint256",
|
||||||
|
"label": "mapping(uint256 => struct NonfungiblePositionManager.Position)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_struct(Position)7092_storage"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint80,t_struct(PoolKey)16521_storage)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint80",
|
||||||
|
"label": "mapping(uint80 => struct PoolAddress.PoolKey)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_struct(PoolKey)16521_storage"
|
||||||
|
},
|
||||||
|
"t_string_storage": {
|
||||||
|
"encoding": "bytes",
|
||||||
|
"label": "string",
|
||||||
|
"numberOfBytes": "32"
|
||||||
|
},
|
||||||
|
"t_struct(Map)3151_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct EnumerableMap.Map",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 3146,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_entries",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_array(t_struct(MapEntry)3143_storage)dyn_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 3150,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_indexes",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_mapping(t_bytes32,t_uint256)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_struct(MapEntry)3143_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct EnumerableMap.MapEntry",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 3140,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_key",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_bytes32"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 3142,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_value",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_struct(PoolKey)16521_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct PoolAddress.PoolKey",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 16516,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "token0",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 16518,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "token1",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 16520,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "fee",
|
||||||
|
"offset": 20,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_uint24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_struct(Position)7092_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct NonfungiblePositionManager.Position",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 7073,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "nonce",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_uint96"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7075,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "operator",
|
||||||
|
"offset": 12,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7077,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "poolId",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_uint80"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7079,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "tickLower",
|
||||||
|
"offset": 10,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_int24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7081,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "tickUpper",
|
||||||
|
"offset": 13,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_int24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7083,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "liquidity",
|
||||||
|
"offset": 16,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_uint128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7085,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "feeGrowthInside0LastX128",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "2",
|
||||||
|
"type": "t_uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7087,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "feeGrowthInside1LastX128",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "3",
|
||||||
|
"type": "t_uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7089,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "tokensOwed0",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "4",
|
||||||
|
"type": "t_uint128"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 7091,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "tokensOwed1",
|
||||||
|
"offset": 16,
|
||||||
|
"slot": "4",
|
||||||
|
"type": "t_uint128"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "160"
|
||||||
|
},
|
||||||
|
"t_struct(Set)3706_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct EnumerableSet.Set",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 3701,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_values",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_array(t_bytes32)dyn_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 3705,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_indexes",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_mapping(t_bytes32,t_uint256)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_struct(UintSet)4092_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct EnumerableSet.UintSet",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 4091,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_inner",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_struct(Set)3706_storage"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_struct(UintToAddressMap)3469_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct EnumerableMap.UintToAddressMap",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 3468,
|
||||||
|
"contract": "contracts/NonfungiblePositionManager.sol:NonfungiblePositionManager",
|
||||||
|
"label": "_inner",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_struct(Map)3151_storage"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "64"
|
||||||
|
},
|
||||||
|
"t_uint128": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint128",
|
||||||
|
"numberOfBytes": "16"
|
||||||
|
},
|
||||||
|
"t_uint176": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint176",
|
||||||
|
"numberOfBytes": "22"
|
||||||
|
},
|
||||||
|
"t_uint24": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint24",
|
||||||
|
"numberOfBytes": "3"
|
||||||
|
},
|
||||||
|
"t_uint256": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint256",
|
||||||
|
"numberOfBytes": "32"
|
||||||
|
},
|
||||||
|
"t_uint80": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint80",
|
||||||
|
"numberOfBytes": "10"
|
||||||
|
},
|
||||||
|
"t_uint96": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint96",
|
||||||
|
"numberOfBytes": "12"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
[
|
{
|
||||||
|
"abi": [
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"anonymous": false,
|
"anonymous": false,
|
||||||
"inputs": [
|
"inputs": [
|
||||||
@ -125,7 +131,7 @@
|
|||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
"internalType": "uint24",
|
"internalType": "uint24",
|
||||||
"name": "fee",
|
"name": "",
|
||||||
"type": "uint24"
|
"type": "uint24"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -144,17 +150,17 @@
|
|||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
"internalType": "address",
|
"internalType": "address",
|
||||||
"name": "tokenA",
|
"name": "",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"internalType": "address",
|
"internalType": "address",
|
||||||
"name": "tokenB",
|
"name": "",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"internalType": "uint24",
|
"internalType": "uint24",
|
||||||
"name": "fee",
|
"name": "",
|
||||||
"type": "uint24"
|
"type": "uint24"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -162,7 +168,7 @@
|
|||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"internalType": "address",
|
"internalType": "address",
|
||||||
"name": "pool",
|
"name": "",
|
||||||
"type": "address"
|
"type": "address"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -182,6 +188,39 @@
|
|||||||
"stateMutability": "view",
|
"stateMutability": "view",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "parameters",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "factory",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "token0",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "token1",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint24",
|
||||||
|
"name": "fee",
|
||||||
|
"type": "uint24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "int24",
|
||||||
|
"name": "tickSpacing",
|
||||||
|
"type": "int24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
{
|
{
|
||||||
@ -195,4 +234,133 @@
|
|||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"storageLayout": {
|
||||||
|
"storage": [
|
||||||
|
{
|
||||||
|
"astId": 2840,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "parameters",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_struct(Parameters)2836_storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 56,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "owner",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "3",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 62,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "feeAmountTickSpacing",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "4",
|
||||||
|
"type": "t_mapping(t_uint24,t_int24)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 72,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "getPool",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "5",
|
||||||
|
"type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint24,t_address)))"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": {
|
||||||
|
"t_address": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "address",
|
||||||
|
"numberOfBytes": "20"
|
||||||
|
},
|
||||||
|
"t_int24": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "int24",
|
||||||
|
"numberOfBytes": "3"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint24,t_address)))": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => mapping(address => mapping(uint24 => address)))",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_mapping(t_address,t_mapping(t_uint24,t_address))"
|
||||||
|
},
|
||||||
|
"t_mapping(t_address,t_mapping(t_uint24,t_address))": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_address",
|
||||||
|
"label": "mapping(address => mapping(uint24 => address))",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_mapping(t_uint24,t_address)"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint24,t_address)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint24",
|
||||||
|
"label": "mapping(uint24 => address)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_address"
|
||||||
|
},
|
||||||
|
"t_mapping(t_uint24,t_int24)": {
|
||||||
|
"encoding": "mapping",
|
||||||
|
"key": "t_uint24",
|
||||||
|
"label": "mapping(uint24 => int24)",
|
||||||
|
"numberOfBytes": "32",
|
||||||
|
"value": "t_int24"
|
||||||
|
},
|
||||||
|
"t_struct(Parameters)2836_storage": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "struct UniswapV3PoolDeployer.Parameters",
|
||||||
|
"members": [
|
||||||
|
{
|
||||||
|
"astId": 2827,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "factory",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "0",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 2829,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "token0",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "1",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 2831,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "token1",
|
||||||
|
"offset": 0,
|
||||||
|
"slot": "2",
|
||||||
|
"type": "t_address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 2833,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "fee",
|
||||||
|
"offset": 20,
|
||||||
|
"slot": "2",
|
||||||
|
"type": "t_uint24"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"astId": 2835,
|
||||||
|
"contract": "contracts/UniswapV3Factory.sol:UniswapV3Factory",
|
||||||
|
"label": "tickSpacing",
|
||||||
|
"offset": 23,
|
||||||
|
"slot": "2",
|
||||||
|
"type": "t_int24"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"numberOfBytes": "96"
|
||||||
|
},
|
||||||
|
"t_uint24": {
|
||||||
|
"encoding": "inplace",
|
||||||
|
"label": "uint24",
|
||||||
|
"numberOfBytes": "3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { gql } from '@apollo/client/core';
|
import { gql } from '@apollo/client/core';
|
||||||
import { GraphQLClient, GraphQLConfig } from '@vulcanize/ipld-eth-client';
|
import { GraphQLClient, GraphQLConfig } from '@vulcanize/ipld-eth-client';
|
||||||
|
|
||||||
|
import { queryGetPool, queryPoolIdToPoolKey, queryPosition } from './queries';
|
||||||
|
|
||||||
export class Client {
|
export class Client {
|
||||||
_config: GraphQLConfig;
|
_config: GraphQLConfig;
|
||||||
_client: GraphQLClient;
|
_client: GraphQLClient;
|
||||||
@ -72,6 +74,13 @@ export class Client {
|
|||||||
liquidity
|
liquidity
|
||||||
tick
|
tick
|
||||||
}
|
}
|
||||||
|
|
||||||
|
... on IncreaseLiquidityEvent {
|
||||||
|
tokenId
|
||||||
|
liquidity
|
||||||
|
amount0
|
||||||
|
amount1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -81,4 +90,42 @@ export class Client {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getPosition (blockHash: string, tokenId: bigint): Promise<any> {
|
||||||
|
const { position } = await this._client.query(
|
||||||
|
gql(queryPosition),
|
||||||
|
{
|
||||||
|
blockHash,
|
||||||
|
tokenId: tokenId.toString()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
async poolIdToPoolKey (blockHash: string, poolId: bigint): Promise<any> {
|
||||||
|
const { poolIdToPoolKey } = await this._client.query(
|
||||||
|
gql(queryPoolIdToPoolKey),
|
||||||
|
{
|
||||||
|
blockHash,
|
||||||
|
poolId: poolId.toString()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return poolIdToPoolKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPool (blockHash: string, token0: string, token1: string, fee: bigint): Promise<any> {
|
||||||
|
const { getPool } = await this._client.query(
|
||||||
|
gql(queryGetPool),
|
||||||
|
{
|
||||||
|
blockHash,
|
||||||
|
token0,
|
||||||
|
token1,
|
||||||
|
fee: fee.toString()
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return getPool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,6 +122,14 @@ export class Database {
|
|||||||
.getOne();
|
.getOne();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getLatestContract (kind: string): Promise<Contract | undefined> {
|
||||||
|
return this._conn.getRepository(Contract)
|
||||||
|
.createQueryBuilder('contract')
|
||||||
|
.where('kind = :kind', { kind })
|
||||||
|
.orderBy('id', 'DESC')
|
||||||
|
.getOne();
|
||||||
|
}
|
||||||
|
|
||||||
async saveContract (address: string, kind: string, startingBlock: number): Promise<void> {
|
async saveContract (address: string, kind: string, startingBlock: number): Promise<void> {
|
||||||
await this._conn.transaction(async (tx) => {
|
await this._conn.transaction(async (tx) => {
|
||||||
const repo = tx.getRepository(Contract);
|
const repo = tx.getRepository(Contract);
|
||||||
|
@ -2,9 +2,10 @@ import debug from 'debug';
|
|||||||
import { DeepPartial } from 'typeorm';
|
import { DeepPartial } from 'typeorm';
|
||||||
import JSONbig from 'json-bigint';
|
import JSONbig from 'json-bigint';
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
|
import assert from 'assert';
|
||||||
|
|
||||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||||
import { GetStorageAt } from '@vulcanize/solidity-mapper';
|
import { GetStorageAt, getStorageValue, StorageLayout } from '@vulcanize/solidity-mapper';
|
||||||
import { Config } from '@vulcanize/util';
|
import { Config } from '@vulcanize/util';
|
||||||
|
|
||||||
import { Database } from './database';
|
import { Database } from './database';
|
||||||
@ -12,9 +13,9 @@ import { Event, UNKNOWN_EVENT_NAME } from './entity/Event';
|
|||||||
import { BlockProgress } from './entity/BlockProgress';
|
import { BlockProgress } from './entity/BlockProgress';
|
||||||
import { Contract, KIND_FACTORY, KIND_POOL, KIND_NFPM } from './entity/Contract';
|
import { Contract, KIND_FACTORY, KIND_POOL, KIND_NFPM } from './entity/Contract';
|
||||||
|
|
||||||
import factoryABI from './artifacts/factory.json';
|
import { abi as factoryABI, storageLayout as factoryStorageLayout } from './artifacts/factory.json';
|
||||||
|
import { abi as nfpmABI, storageLayout as nfpmStorageLayout } from './artifacts/NonfungiblePositionManager.json';
|
||||||
import poolABI from './artifacts/pool.json';
|
import poolABI from './artifacts/pool.json';
|
||||||
import nfpmABI from './artifacts/NonfungiblePositionManager.json';
|
|
||||||
|
|
||||||
// TODO: Move to config.
|
// TODO: Move to config.
|
||||||
const MAX_EVENTS_BLOCK_RANGE = 1000;
|
const MAX_EVENTS_BLOCK_RANGE = 1000;
|
||||||
@ -33,6 +34,13 @@ type ResultEvent = {
|
|||||||
proof: string;
|
proof: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface ValueResult {
|
||||||
|
value: any;
|
||||||
|
proof: {
|
||||||
|
data: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Indexer {
|
export class Indexer {
|
||||||
_config: Config;
|
_config: Config;
|
||||||
_db: Database
|
_db: Database
|
||||||
@ -374,4 +382,49 @@ export class Indexer {
|
|||||||
|
|
||||||
return this._db.getEventsInRange(fromBlockNumber, toBlockNumber);
|
return this._db.getEventsInRange(fromBlockNumber, toBlockNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async position (blockHash: string, tokenId: string) {
|
||||||
|
const nfpmContract = await this._db.getLatestContract('nfpm');
|
||||||
|
assert(nfpmContract, 'No NFPM contract watched.');
|
||||||
|
const { value, proof } = await this._getStorageValue(nfpmStorageLayout, blockHash, nfpmContract.address, '_positions', BigInt(tokenId));
|
||||||
|
|
||||||
|
return {
|
||||||
|
...value,
|
||||||
|
proof
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async poolIdToPoolKey (blockHash: string, poolId: string) {
|
||||||
|
const nfpmContract = await this._db.getLatestContract('nfpm');
|
||||||
|
assert(nfpmContract, 'No NFPM contract watched.');
|
||||||
|
const { value, proof } = await this._getStorageValue(nfpmStorageLayout, blockHash, nfpmContract.address, '_poolIdToPoolKey', BigInt(poolId));
|
||||||
|
|
||||||
|
return {
|
||||||
|
...value,
|
||||||
|
proof
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async getPool (blockHash: string, token0: string, token1: string, fee: string) {
|
||||||
|
const factoryContract = await this._db.getLatestContract('factory');
|
||||||
|
assert(factoryContract, 'No Factory contract watched.');
|
||||||
|
const { value, proof } = await this._getStorageValue(factoryStorageLayout, blockHash, factoryContract.address, 'getPool', token0, token1, BigInt(fee));
|
||||||
|
|
||||||
|
return {
|
||||||
|
pool: value,
|
||||||
|
proof
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move into base/class or framework package.
|
||||||
|
async _getStorageValue (storageLayout: StorageLayout, blockHash: string, token: string, variable: string, ...mappingKeys: any[]): Promise<ValueResult> {
|
||||||
|
return getStorageValue(
|
||||||
|
storageLayout,
|
||||||
|
this._getStorageAt,
|
||||||
|
blockHash,
|
||||||
|
token,
|
||||||
|
variable,
|
||||||
|
...mappingKeys
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,3 +12,49 @@ query getEvents($blockHash: String!, $token: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const queryPosition = gql`
|
||||||
|
query getPosition($blockHash: String!, $tokenId: String!) {
|
||||||
|
position(blockHash: $blockHash, tokenId: $tokenId) {
|
||||||
|
nonce
|
||||||
|
operator
|
||||||
|
poolId
|
||||||
|
tickLower
|
||||||
|
tickUpper
|
||||||
|
liquidity
|
||||||
|
feeGrowthInside0LastX128
|
||||||
|
feeGrowthInside1LastX128
|
||||||
|
tokensOwed0
|
||||||
|
tokensOwed1
|
||||||
|
|
||||||
|
proof {
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const queryPoolIdToPoolKey = gql`
|
||||||
|
query poolIdToPoolKey($blockHash: String!, $poolId: String!) {
|
||||||
|
poolIdToPoolKey(blockHash: $blockHash, poolId: $poolId) {
|
||||||
|
token0
|
||||||
|
token1
|
||||||
|
fee
|
||||||
|
|
||||||
|
proof {
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const queryGetPool = gql`
|
||||||
|
query getPool($blockHash: String!, $token0: String!, $token1: String!, $fee: String!) {
|
||||||
|
getPool(blockHash: $blockHash, token0: $token0, token1: $token1, fee: $fee) {
|
||||||
|
pool
|
||||||
|
proof {
|
||||||
|
data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
@ -72,6 +72,21 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
|
|||||||
|
|
||||||
const events = await indexer.getEventsInRange(fromBlockNumber, toBlockNumber);
|
const events = await indexer.getEventsInRange(fromBlockNumber, toBlockNumber);
|
||||||
return events.map(event => indexer.getResultEvent(event));
|
return events.map(event => indexer.getResultEvent(event));
|
||||||
|
},
|
||||||
|
|
||||||
|
position: (_: any, { blockHash, tokenId }: { blockHash: string, tokenId: string }) => {
|
||||||
|
log('position', blockHash, tokenId);
|
||||||
|
return indexer.position(blockHash, tokenId);
|
||||||
|
},
|
||||||
|
|
||||||
|
poolIdToPoolKey: (_: any, { blockHash, poolId }: { blockHash: string, poolId: string }) => {
|
||||||
|
log('poolIdToPoolKey', blockHash, poolId);
|
||||||
|
return indexer.poolIdToPoolKey(blockHash, poolId);
|
||||||
|
},
|
||||||
|
|
||||||
|
getPool: (_: any, { blockHash, token0, token1, fee }: { blockHash: string, token0: string, token1: string, fee: string }) => {
|
||||||
|
log('getPool', blockHash, token0, token1, fee);
|
||||||
|
return indexer.getPool(blockHash, token0, token1, fee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -202,12 +202,12 @@ type Query {
|
|||||||
|
|
||||||
position(
|
position(
|
||||||
blockHash: String!
|
blockHash: String!
|
||||||
tokenId: BigInt!
|
tokenId: String!
|
||||||
): ResultPosition
|
): ResultPosition
|
||||||
|
|
||||||
poolIdToPoolKey(
|
poolIdToPoolKey(
|
||||||
blockHash: String!
|
blockHash: String!
|
||||||
poolId: BigInt!
|
poolId: String!
|
||||||
): ResultPoolKey
|
): ResultPoolKey
|
||||||
|
|
||||||
# Factory
|
# Factory
|
||||||
@ -216,7 +216,7 @@ type Query {
|
|||||||
blockHash: String!
|
blockHash: String!
|
||||||
token0: String!
|
token0: String!
|
||||||
token1: String!
|
token1: String!
|
||||||
fee: BigInt!
|
fee: String!
|
||||||
): ResultGetPool
|
): ResultGetPool
|
||||||
|
|
||||||
# Pool
|
# Pool
|
||||||
|
Loading…
Reference in New Issue
Block a user