Add test:init in uni-watcher. (#204)

Co-authored-by: prathamesh0 <prathamesh.musale0@gmail.com>
This commit is contained in:
Ashwin Phatak 2021-08-11 16:27:42 +05:30 committed by GitHub
parent cbc8dce88b
commit 053695a3e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 164 additions and 81 deletions

View File

@ -18,6 +18,12 @@ The default config files used by the watchers assume the following services are
* `vulcanize/ipld-eth-server` with native GQL API enabled, on port 8082
* `postgraphile` on the `vulcanize/ipld-eth-server` database, on port 5000
#### Note
* In `vulcanize/ipld-eth-server`, add the following statement to `[ethereum]` section in `environments/config.toml`:
`chainConfig = "./chain.json" # ETH_CHAIN_CONFIG`
### Databases
Note: Requires `postgres12`.

View File

@ -54,13 +54,13 @@ export const createResolvers = async (indexer: Indexer): Promise<any> => {
},
mints: async (_: any, { first, orderBy, orderDirection, where }: { first: number, orderBy: string, orderDirection: OrderDirection, where: { [key: string]: any } }) => {
log('burns', first, orderBy, orderDirection, where);
log('mints', first, orderBy, orderDirection, where);
return indexer.getEntities(Mint, {}, where, { limit: first, orderBy, orderDirection }, ['pool', 'transaction']);
},
pool: async (_: any, { id, block = {} }: { id: string, block: BlockHeight }) => {
log('bundle', id, block);
log('pool', id, block);
return indexer.getPool(id, block);
},
@ -72,7 +72,7 @@ export const createResolvers = async (indexer: Indexer): Promise<any> => {
},
pools: async (_: any, { block = {}, first, orderBy, orderDirection, where = {} }: { block: BlockHeight, first: number, orderBy: string, orderDirection: OrderDirection, where: { [key: string]: any } }) => {
log('burns', block, first, orderBy, orderDirection, where);
log('pools', block, first, orderBy, orderDirection, where);
return indexer.getEntities(Pool, block, where, { limit: first, orderBy, orderDirection }, ['token0', 'token1']);
},
@ -108,7 +108,7 @@ export const createResolvers = async (indexer: Indexer): Promise<any> => {
},
tokenHourDatas: async (_: any, { first, skip, orderBy, orderDirection, where }: { first: number, skip: number, orderBy: string, orderDirection: OrderDirection, where: { [key: string]: any } }) => {
log('tokenDayDatas', first, skip, orderBy, orderDirection, where);
log('tokenHourDatas', first, skip, orderBy, orderDirection, where);
return indexer.getEntities(TokenHourData, {}, where, { limit: first, skip, orderBy, orderDirection });
},
@ -126,7 +126,7 @@ export const createResolvers = async (indexer: Indexer): Promise<any> => {
},
positions: async (_: any, { first, where }: { first: number, where: { [key: string]: any } }) => {
log('uniswapDayDatas', first, where);
log('positions', first, where);
return indexer.getEntities(Position, {}, where, { limit: first }, ['pool', 'token0', 'token1', 'tickLower', 'tickUpper', 'transaction']);
}

View File

@ -758,11 +758,12 @@ describe('uni-info-watcher', () => {
const deadline = 1634367993;
before(async () => {
// Get the NFPM contract.
const latestContract = await uniClient.getLatestContract('nfpm');
expect(latestContract.address).to.not.be.empty;
// Get the NFPM contract address.
const nfpmContract = await uniClient.getContract('nfpm');
expect(nfpmContract).to.not.be.empty;
nfpm = new Contract(latestContract.address, NFPM_ABI, signer);
// Initialize the NFPM contract.
nfpm = new Contract(nfpmContract.address, NFPM_ABI, signer);
// Create Pool.
createPool(factory, token0Address, token1Address, fee);
@ -772,7 +773,7 @@ describe('uni-info-watcher', () => {
eventValue = await watchEvent(uniClient, eventType);
// Sleeping for 10 sec for the event to be processed.
await wait(10000); // not needed
await wait(10000);
// Reinitializing the pool variable.
const poolAddress = eventValue.event.pool;

View File

@ -13,7 +13,8 @@
"lint": "eslint .",
"build": "tsc",
"watch:contract": "ts-node src/cli/watch-contract.ts --configFile environments/local.toml",
"smoke-test": "mocha src/smoke.test.ts"
"test:init": "ts-node test/init.ts",
"smoke-test": "yarn test:init && mocha src/smoke.test.ts"
},
"repository": {
"type": "git",

View File

@ -1,7 +1,7 @@
import { gql } from '@apollo/client/core';
import { GraphQLClient, GraphQLConfig } from '@vulcanize/ipld-eth-client';
import { queryGetPool, queryPoolIdToPoolKey, queryPosition, queryEvents, subscribeEvents, queryLatestContract } from './queries';
import { queryGetPool, queryPoolIdToPoolKey, queryPosition, queryEvents, subscribeEvents, queryGetContract } from './queries';
export class Client {
_config: GraphQLConfig;
@ -72,14 +72,14 @@ export class Client {
return getPool;
}
async getLatestContract (type: string): Promise<any> {
const { latestContract } = await this._client.query(
gql(queryLatestContract),
async getContract (type: string): Promise<any> {
const { getContract } = await this._client.query(
gql(queryGetContract),
{
type
}
);
return latestContract;
return getContract;
}
}

View File

@ -605,10 +605,8 @@ export class Indexer {
);
}
async getLatestContract (type: string): Promise<any> {
async getContract (type: string): Promise<any> {
const contract = await this._db.getLatestContract(type);
assert(contract, `No ${type} contract watched.`);
return contract;
}
}

View File

@ -156,9 +156,9 @@ query getPool($blockHash: String!, $token0: String!, $token1: String!, $fee: Str
}
`;
export const queryLatestContract = gql`
query queryLatestContract($type: String!) {
latestContract(type: $type) {
export const queryGetContract = gql`
query queryGetContract($type: String!) {
getContract(type: $type) {
address
}
}

View File

@ -91,9 +91,9 @@ export const createResolvers = async (indexer: Indexer, eventWatcher: EventWatch
return indexer.getPool(blockHash, token0, token1, fee);
},
latestContract: (_: any, { type }: { type: string }) => {
log('latestContract', type);
return indexer.getLatestContract(type);
getContract: (_: any, { type }: { type: string }) => {
log('getContract', type);
return indexer.getContract(type);
}
}
};

View File

@ -205,7 +205,7 @@ type Query {
# NonfungiblePositionManager
latestContract(
getContract(
type: String!
): Contract

View File

@ -14,15 +14,13 @@ import {
getMinTick,
getMaxTick,
approveToken,
deployWETH9Token,
deployNFPM
NFPM_ABI
} from '@vulcanize/util/test';
import { Client as UniClient } from '@vulcanize/uni-watcher';
import { getCache } from '@vulcanize/cache';
import { EthClient } from '@vulcanize/ipld-eth-client';
import {
abi as FACTORY_ABI,
bytecode as FACTORY_BYTECODE
abi as FACTORY_ABI
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json';
import {
abi as POOL_ABI
@ -30,7 +28,6 @@ import {
import { Indexer } from './indexer';
import { Database } from './database';
import { watchContract } from './utils/index';
import {
testCreatePool,
testInitialize,
@ -53,9 +50,9 @@ describe('uni-watcher', () => {
let poolCallee: Contract;
let token0Address: string;
let token1Address: string;
let weth9Address: string;
let nfpm: Contract;
let nfpmTokenId: number;
let tickLower: number;
let tickUpper: number;
let config: Config;
@ -113,21 +110,17 @@ describe('uni-watcher', () => {
await db.close();
});
it('should deploy contract factory', async () => {
// Deploy factory from uniswap package.
const Factory = new ethers.ContractFactory(FACTORY_ABI, FACTORY_BYTECODE, signer);
factory = await Factory.deploy();
it('should have a watched Factory contract', async () => {
// Get the factory contract address.
const factoryContract = await uniClient.getContract('factory');
expect(factoryContract).to.not.be.empty;
expect(factory.address).to.not.be.empty;
});
it('should watch factory contract', async () => {
// Watch factory contract.
await watchContract(db, factory.address, 'factory', 100);
// Initialize the factory contract.
factory = new Contract(factoryContract.address, FACTORY_ABI, signer);
// Verifying with the db.
const indexer = new Indexer(config, db, ethClient, postgraphileClient);
assert(await indexer.isUniswapContract(factory.address), 'Factory contract not added to database.');
assert(await indexer.isUniswapContract(factory.address), 'Factory contract not added to the database.');
});
it('should deploy 2 tokens', async () => {
@ -252,25 +245,17 @@ describe('uni-watcher', () => {
});
});
it('should deploy a WETH9 token', async () => {
// Deploy weth9 token.
weth9Address = await deployWETH9Token(signer);
expect(weth9Address).to.not.be.empty;
});
it('should have a watched NFPM contract', async () => {
// Get the NFPM contract address.
const nfpmContract = await uniClient.getContract('nfpm');
expect(nfpmContract).to.not.be.empty;
it('should deploy NonfungiblePositionManager', async () => {
// Deploy NonfungiblePositionManager.
nfpm = await deployNFPM(signer, factory, weth9Address);
expect(nfpm.address).to.not.be.empty;
});
it('should watch NonfungiblePositionManager contract', async () => {
// Watch NFPM contract.
await watchContract(db, nfpm.address, 'nfpm', 100);
// Initialize the NFPM contract.
nfpm = new Contract(nfpmContract.address, NFPM_ABI, signer);
// Verifying with the db.
const indexer = new Indexer(config, db, ethClient, postgraphileClient);
assert(await indexer.isUniswapContract(nfpm.address), 'NonfungiblePositionManager contract not added to database.');
assert(await indexer.isUniswapContract(nfpm.address), 'NFPM contract not added to the database.');
});
it('should mint specified amount: nfpm', done => {
@ -302,7 +287,6 @@ describe('uni-watcher', () => {
// Subscribe using UniClient.
const subscription = await uniClient.watchEvents((value: any) => {
// TODO Verify what should amount values be checked against.
if (value.event.__typename === 'MintEvent') {
const expectedContract: string = pool.address;
const expectedSender: string = nfpm.address;
@ -315,11 +299,13 @@ describe('uni-watcher', () => {
const from = '0x0000000000000000000000000000000000000000';
checkTransferEvent(value, expectedContract, from, recipient);
nfpmTokenId = Number(value.event.tokenId);
}
if (value.event.__typename === 'IncreaseLiquidityEvent') {
const expectedTokenId = nfpmTokenId;
const expectedContract: string = nfpm.address;
checkIncreaseLiquidityEvent(value, expectedContract, amount1Desired);
checkIncreaseLiquidityEvent(value, expectedTokenId, expectedContract, amount1Desired);
if (subscription) {
subscription.unsubscribe();
@ -350,7 +336,6 @@ describe('uni-watcher', () => {
it('should increase liquidity', done => {
(async () => {
const tokenId = 1;
const amount0Desired = 15;
const amount1Desired = 15;
const amount0Min = 0;
@ -367,9 +352,10 @@ describe('uni-watcher', () => {
checkMintEvent(value, expectedContract, expectedSender, exptectedOwner, tickLower, tickUpper, amount0Desired);
}
if (value.event.__typename === 'IncreaseLiquidityEvent') {
const expectedTokenId = nfpmTokenId;
const expectedContract: string = nfpm.address;
checkIncreaseLiquidityEvent(value, expectedContract, amount0Desired);
checkIncreaseLiquidityEvent(value, expectedTokenId, expectedContract, amount0Desired);
if (subscription) {
subscription.unsubscribe();
@ -380,7 +366,7 @@ describe('uni-watcher', () => {
// Position manger increase liquidity.
const transaction: ContractTransaction = await nfpm.increaseLiquidity({
tokenId,
tokenId: nfpmTokenId,
amount0Desired,
amount1Desired,
amount0Min,
@ -395,7 +381,6 @@ describe('uni-watcher', () => {
it('should decrease liquidity', done => {
(async () => {
const tokenId = 1;
const liquidity = 5;
const amount0Min = 0;
const amount1Min = 0;
@ -410,9 +395,10 @@ describe('uni-watcher', () => {
checkBurnEvent(value, expectedContract, exptectedOwner, tickLower, tickUpper, liquidity);
}
if (value.event.__typename === 'DecreaseLiquidityEvent') {
const expectedTokenId = nfpmTokenId;
const expectedContract: string = nfpm.address;
checkDecreaseLiquidityEvent(value, expectedContract, liquidity);
checkDecreaseLiquidityEvent(value, expectedTokenId, expectedContract, liquidity);
if (subscription) {
subscription.unsubscribe();
@ -423,7 +409,7 @@ describe('uni-watcher', () => {
// Position manger decrease liquidity.
const transaction: ContractTransaction = await nfpm.decreaseLiquidity({
tokenId,
tokenId: nfpmTokenId,
liquidity,
amount0Min,
amount1Min,
@ -437,7 +423,6 @@ describe('uni-watcher', () => {
xit('should collect fees', done => {
(async () => {
const tokenId = 1;
const amount0Max = 15;
const amount1Max = 15;
@ -450,9 +435,10 @@ describe('uni-watcher', () => {
checkBurnEvent(value, expectedContract, exptectedOwner, tickLower, tickUpper, 0);
}
if (value.event.__typename === 'CollectEvent') {
const expectedTokenId = nfpmTokenId;
const expectedContract: string = nfpm.address;
checksCollectEvent(value, expectedContract, recipient);
checksCollectEvent(value, expectedTokenId, expectedContract, recipient);
if (subscription) {
subscription.unsubscribe();
@ -463,7 +449,7 @@ describe('uni-watcher', () => {
// Position manger collect.
const transaction: ContractTransaction = await nfpm.collect({
tokenId,
tokenId: nfpmTokenId,
recipient,
amount0Max,
amount1Max

View File

@ -0,0 +1,97 @@
import { Contract, ethers, Signer } from 'ethers';
import assert from 'assert';
import { Client as UniClient } from '@vulcanize/uni-watcher';
import {
getConfig
} from '@vulcanize/util';
import {
deployWETH9Token,
deployNFPM
} from '@vulcanize/util/test';
import {
abi as FACTORY_ABI,
bytecode as FACTORY_BYTECODE
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json';
import { Database } from '../src/database';
import { watchContract } from '../src/utils/index';
const NETWORK_RPC_URL = 'http://localhost:8545';
const deployFactoryContract = async (db: Database, signer: Signer): Promise<Contract> => {
// Deploy factory from uniswap package.
const Factory = new ethers.ContractFactory(FACTORY_ABI, FACTORY_BYTECODE, signer);
const factory = await Factory.deploy();
assert(factory.address, 'Factory contract not deployed.');
// Watch factory contract.
await watchContract(db, factory.address, 'factory', 100);
return factory;
};
const deployNFPMContract = async (db: Database, signer: Signer, factory: Contract): Promise<void> => {
// Deploy weth9 token.
const weth9Address = await deployWETH9Token(signer);
assert(weth9Address, 'WETH9 token not deployed.');
// Deploy NonfungiblePositionManager.
const nfpm = await deployNFPM(signer, factory, weth9Address);
assert(nfpm.address, 'NFPM contract not deployed.');
// Watch NFPM contract.
await watchContract(db, nfpm.address, 'nfpm', 100);
};
const main = async () => {
// Get config.
const configFile = './environments/local.toml';
const config = await getConfig(configFile);
const { database: dbConfig, server: { host, port } } = config;
assert(dbConfig, 'Missing dbConfig.');
assert(host, 'Missing host.');
assert(port, 'Missing port.');
// Initialize uniClient.
const endpoint = `http://${host}:${port}/graphql`;
const gqlEndpoint = endpoint;
const gqlSubscriptionEndpoint = endpoint;
const uniClient = new UniClient({
gqlEndpoint,
gqlSubscriptionEndpoint
});
// Initialize database.
const db = new Database(dbConfig);
await db.init();
const provider = new ethers.providers.JsonRpcProvider(NETWORK_RPC_URL);
const signer = provider.getSigner();
let factory: Contract;
// Checking whether factory is deployed.
const factoryContract = await uniClient.getContract('factory');
if (factoryContract == null) {
factory = await deployFactoryContract(db, signer);
} else {
factory = new Contract(factoryContract.address, FACTORY_ABI, signer);
}
// Checking whether NFPM is deployed.
const nfpmContract = await uniClient.getContract('nfpm');
if (nfpmContract == null) {
await deployNFPMContract(db, signer, factory);
}
// Closing the database.
await db.close();
};
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});

View File

@ -88,7 +88,6 @@ export const checkPoolCreatedEvent = (
fee: number): string => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('PoolCreatedEvent');
const tokens = new Set([token0Address, token1Address]);
expect(new Set([value.event.token0, value.event.token1])).to.eql(tokens);
expect(value.event.fee).to.equal(fee.toString());
@ -105,7 +104,6 @@ export const checkInitializeEvent = (
tick: number): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('InitializeEvent');
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
expect(value.event.tick).to.equal(tick.toString());
};
@ -120,7 +118,6 @@ export const checkMintEvent = (
amount: number): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('MintEvent');
expect(value.event.sender).to.equal(expectedSender);
expect(value.event.owner).to.equal(exptectedOwner);
expect(value.event.tickLower).to.equal(tickLower.toString());
@ -139,7 +136,6 @@ export const checkBurnEvent = (
amount: number): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('BurnEvent');
expect(value.event.owner).to.equal(exptectedOwner);
expect(value.event.tickLower).to.equal(tickLower.toString());
expect(value.event.tickUpper).to.equal(tickUpper.toString());
@ -158,7 +154,6 @@ export const checkSwapEvent = (
): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('SwapEvent');
expect(value.event.sender).to.equal(expectedSender);
expect(value.event.recipient).to.equal(recipient);
expect(value.event.amount0).to.not.be.empty;
@ -176,20 +171,19 @@ export const checkTransferEvent = (
): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('TransferEvent');
expect(value.event.from).to.equal(from);
expect(value.event.to).to.equal(to);
expect(value.event.tokenId).to.equal('1');
};
export const checkIncreaseLiquidityEvent = (
value: any,
expectedTokenId: number,
expectedContract: string,
amount1Desired: number
): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.tokenId).to.equal('1');
expect(value.event.tokenId).to.equal(expectedTokenId.toString());
expect(value.event.liquidity).to.equal(amount1Desired.toString());
expect(value.event.amount0).to.equal(amount1Desired.toString());
expect(value.event.amount1).to.equal(amount1Desired.toString());
@ -197,13 +191,13 @@ export const checkIncreaseLiquidityEvent = (
export const checkDecreaseLiquidityEvent = (
value: any,
expectedTokenId: number,
expectedContract: string,
liquidity: number
): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('DecreaseLiquidityEvent');
expect(value.event.tokenId).to.equal('1');
expect(value.event.tokenId).to.equal(expectedTokenId.toString());
expect(value.event.liquidity).to.equal(liquidity.toString());
expect(value.event.amount0).to.not.be.empty;
expect(value.event.amount1).to.not.be.empty;
@ -211,13 +205,13 @@ export const checkDecreaseLiquidityEvent = (
export const checksCollectEvent = (
value: any,
expectedTokenId: number,
expectedContract: string,
recipient: string
): void => {
checkEventCommonValues(value, expectedContract);
expect(value.event.__typename).to.equal('CollectEvent');
expect(value.event.tokenId).to.equal('1');
expect(value.event.tokenId).to.equal(expectedTokenId.toString());
expect(value.event.recipient).to.equal(recipient);
expect(value.event.amount0).to.not.be.empty;
expect(value.event.amount1).to.not.be.empty;