mirror of
https://github.com/cerc-io/watcher-ts
synced 2025-01-23 11:39:05 +00:00
Smoke test for uni-info-watcher (#184)
* Smoke test for uni-info-watcher and refactor token deployment code. * Test for Token entity after PoolCreated event. * Test for Pool entity after PoolCreated event. * Tests for entities after InitializeEvent. Co-authored-by: prathamesh0 <prathamesh.musale0@gmail.com>
This commit is contained in:
parent
73e0475dfa
commit
a9d411c6df
@ -23,5 +23,13 @@
|
|||||||
"allowArgumentsExplicitlyTypedAsAny": true
|
"allowArgumentsExplicitlyTypedAsAny": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.test.ts"],
|
||||||
|
"rules": {
|
||||||
|
"no-unused-expressions": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
4
packages/uni-info-watcher/.mocharc.yml
Normal file
4
packages/uni-info-watcher/.mocharc.yml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
timeout: '20000'
|
||||||
|
bail: true
|
||||||
|
exit: true # TODO: Find out why the program doesn't exit on its own.
|
||||||
|
require: 'ts-node/register'
|
@ -22,7 +22,8 @@
|
|||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"generate:schema": "get-graphql-schema https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-alt > docs/analysis/schema/full-schema.graphql",
|
"generate:schema": "get-graphql-schema https://api.thegraph.com/subgraphs/name/ianlapham/uniswap-v3-alt > docs/analysis/schema/full-schema.graphql",
|
||||||
"lint:schema": "graphql-schema-linter"
|
"lint:schema": "graphql-schema-linter",
|
||||||
|
"smoke-test": "mocha src/smoke.test.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/chance": "^1.1.2",
|
"@types/chance": "^1.1.2",
|
||||||
@ -41,6 +42,8 @@
|
|||||||
"get-graphql-schema": "^2.1.2",
|
"get-graphql-schema": "^2.1.2",
|
||||||
"graphql-schema-linter": "^2.0.1",
|
"graphql-schema-linter": "^2.0.1",
|
||||||
"mocha": "^8.4.0",
|
"mocha": "^8.4.0",
|
||||||
"nodemon": "^2.0.7"
|
"nodemon": "^2.0.7",
|
||||||
|
"ts-node": "^10.0.0",
|
||||||
|
"typescript": "^4.3.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
186
packages/uni-info-watcher/src/smoke.test.ts
Normal file
186
packages/uni-info-watcher/src/smoke.test.ts
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
import { expect } from 'chai';
|
||||||
|
import { ethers, Contract, Signer } from 'ethers';
|
||||||
|
import { request } from 'graphql-request';
|
||||||
|
import 'mocha';
|
||||||
|
|
||||||
|
import { Config, getConfig, wait, deployTokens, createPool, initializePool } from '@vulcanize/util';
|
||||||
|
import { Client as UniClient, watchEvent } from '@vulcanize/uni-watcher';
|
||||||
|
import {
|
||||||
|
abi as FACTORY_ABI
|
||||||
|
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Factory.sol/UniswapV3Factory.json';
|
||||||
|
import {
|
||||||
|
abi as POOL_ABI
|
||||||
|
} from '@uniswap/v3-core/artifacts/contracts/UniswapV3Pool.sol/UniswapV3Pool.json';
|
||||||
|
|
||||||
|
import {
|
||||||
|
queryFactory,
|
||||||
|
queryBundle,
|
||||||
|
queryToken,
|
||||||
|
queryPoolsByTokens,
|
||||||
|
queryPoolById,
|
||||||
|
queryPoolDayData
|
||||||
|
} from '../test/queries';
|
||||||
|
|
||||||
|
const NETWORK_RPC_URL = 'http://localhost:8545';
|
||||||
|
|
||||||
|
const TICK_MIN = -887272;
|
||||||
|
|
||||||
|
describe('uni-info-watcher', () => {
|
||||||
|
let factory: Contract;
|
||||||
|
let pool: Contract;
|
||||||
|
let token0Address: string;
|
||||||
|
let token1Address: string;
|
||||||
|
|
||||||
|
let signer: Signer;
|
||||||
|
let config: Config;
|
||||||
|
let endpoint: string;
|
||||||
|
let uniClient: UniClient;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
const provider = new ethers.providers.JsonRpcProvider(NETWORK_RPC_URL);
|
||||||
|
signer = provider.getSigner();
|
||||||
|
|
||||||
|
const configFile = './environments/local.toml';
|
||||||
|
config = await getConfig(configFile);
|
||||||
|
|
||||||
|
const { upstream, server: { host, port } } = config;
|
||||||
|
endpoint = `http://${host}:${port}/graphql`;
|
||||||
|
|
||||||
|
const { uniWatcher: { gqlEndpoint, gqlSubscriptionEndpoint } } = upstream;
|
||||||
|
uniClient = new UniClient({
|
||||||
|
gqlEndpoint,
|
||||||
|
gqlSubscriptionEndpoint
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a Factory entity', async () => {
|
||||||
|
// Getting the Factory from uni-info-watcher graphQL endpoint.
|
||||||
|
const data = await request(endpoint, queryFactory);
|
||||||
|
expect(data.factories).to.not.be.empty;
|
||||||
|
|
||||||
|
// Initializing the factory variable.
|
||||||
|
const factoryAddress = data.factories[0].id;
|
||||||
|
factory = new ethers.Contract(factoryAddress, FACTORY_ABI, signer);
|
||||||
|
expect(factory.address).to.not.be.empty;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should have a Bundle entity', async () => {
|
||||||
|
// Getting the Bundle from uni-info-watcher graphQL endpoint.
|
||||||
|
const data = await request(endpoint, queryBundle);
|
||||||
|
expect(data.bundles).to.not.be.empty;
|
||||||
|
|
||||||
|
const bundleId = '1';
|
||||||
|
expect(data.bundles[0].id).to.equal(bundleId);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('PoolCreatedEvent', () => {
|
||||||
|
// NOTE Skipping checking entity updates that cannot be gotten using queries.
|
||||||
|
|
||||||
|
const fee = 500;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
// Deploy 2 tokens.
|
||||||
|
({ token0Address, token1Address } = await deployTokens(signer));
|
||||||
|
expect(token0Address).to.not.be.empty;
|
||||||
|
expect(token1Address).to.not.be.empty;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not have Token entities', async () => {
|
||||||
|
// Check that Token entities are absent.
|
||||||
|
const data0 = await request(endpoint, queryToken, { id: token0Address });
|
||||||
|
expect(data0.token).to.be.null;
|
||||||
|
|
||||||
|
const data1 = await request(endpoint, queryToken, { id: token0Address });
|
||||||
|
expect(data1.token).to.be.null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create pool', async () => {
|
||||||
|
// Create Pool.
|
||||||
|
createPool(factory, token0Address, token1Address, fee);
|
||||||
|
|
||||||
|
// Wait for PoolCreatedEvent.
|
||||||
|
const eventType = 'PoolCreatedEvent';
|
||||||
|
await watchEvent(uniClient, eventType);
|
||||||
|
|
||||||
|
// Sleeping for 5 sec for the entities to be processed.
|
||||||
|
await wait(5000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create Token entities', async () => {
|
||||||
|
// Check that Token entities are present.
|
||||||
|
const data0 = await request(endpoint, queryToken, { id: token0Address });
|
||||||
|
expect(data0.token).to.not.be.null;
|
||||||
|
|
||||||
|
const data1 = await request(endpoint, queryToken, { id: token0Address });
|
||||||
|
expect(data1.token).to.not.be.null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create a Pool entity', async () => {
|
||||||
|
const variables = {
|
||||||
|
tokens: [token0Address, token1Address]
|
||||||
|
};
|
||||||
|
// Getting the Pool that has the deployed tokens.
|
||||||
|
const data = await request(endpoint, queryPoolsByTokens, variables);
|
||||||
|
expect(data.pools).to.have.lengthOf(1);
|
||||||
|
|
||||||
|
// Initializing the pool variable.
|
||||||
|
const poolAddress = data.pools[0].id;
|
||||||
|
pool = new Contract(poolAddress, POOL_ABI, signer);
|
||||||
|
expect(pool.address).to.not.be.empty;
|
||||||
|
|
||||||
|
expect(data.pools[0].feeTier).to.be.equal(fee.toString());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('InitializeEvent', () => {
|
||||||
|
const sqrtPrice = '4295128939';
|
||||||
|
const tick = TICK_MIN;
|
||||||
|
|
||||||
|
it('should not have pool entity initialized', async () => {
|
||||||
|
const data = await request(endpoint, queryPoolById, { id: pool.address });
|
||||||
|
expect(data.pool.sqrtPrice).to.not.be.equal(sqrtPrice);
|
||||||
|
expect(data.pool.tick).to.be.null;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should initialize pool', async () => {
|
||||||
|
initializePool(pool, sqrtPrice);
|
||||||
|
|
||||||
|
// Wait for InitializeEvent.
|
||||||
|
const eventType = 'InitializeEvent';
|
||||||
|
await watchEvent(uniClient, eventType);
|
||||||
|
|
||||||
|
// Sleeping for 5 sec for the entities to be processed.
|
||||||
|
await wait(5000);
|
||||||
|
|
||||||
|
const data = await request(endpoint, queryPoolById, { id: pool.address });
|
||||||
|
expect(data.pool.sqrtPrice).to.be.equal(sqrtPrice);
|
||||||
|
expect(data.pool.tick).to.be.equal(tick.toString());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update PoolDayData entity', async () => {
|
||||||
|
// Get the latest PoolDayData.
|
||||||
|
const variables = {
|
||||||
|
first: 1,
|
||||||
|
orderBy: 'date',
|
||||||
|
orderDirection: 'desc',
|
||||||
|
pool: pool.address
|
||||||
|
};
|
||||||
|
const data = await request(endpoint, queryPoolDayData, variables);
|
||||||
|
expect(data.poolDayDatas).to.not.be.empty;
|
||||||
|
|
||||||
|
const dayPoolID: string = data.poolDayDatas[0].id;
|
||||||
|
const poolID: string = dayPoolID.split('-')[0];
|
||||||
|
const dayID: number = +dayPoolID.split('-')[1];
|
||||||
|
const date = data.poolDayDatas[0].date;
|
||||||
|
const tvlUSD = data.poolDayDatas[0].tvlUSD;
|
||||||
|
|
||||||
|
const dayStartTimestamp = dayID * 86400;
|
||||||
|
const poolData = await request(endpoint, queryPoolById, { id: pool.address });
|
||||||
|
const totalValueLockedUSD: string = poolData.pool.totalValueLockedUSD;
|
||||||
|
|
||||||
|
expect(poolID).to.be.equal(pool.address);
|
||||||
|
expect(date).to.be.equal(dayStartTimestamp);
|
||||||
|
expect(tvlUSD).to.be.equal(totalValueLockedUSD);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
54
packages/uni-info-watcher/test/queries.ts
Normal file
54
packages/uni-info-watcher/test/queries.ts
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
import { gql } from 'graphql-request';
|
||||||
|
|
||||||
|
export const queryToken = gql`
|
||||||
|
query queryToken($id: ID!) {
|
||||||
|
token(id: $id) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Getting the first Factory entity.
|
||||||
|
export const queryFactory = gql`
|
||||||
|
{
|
||||||
|
factories(first: 1) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Getting the first Bundle entity.
|
||||||
|
export const queryBundle = gql`
|
||||||
|
{
|
||||||
|
bundles(first: 1) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Getting Pool by id.
|
||||||
|
export const queryPoolById = gql`
|
||||||
|
query queryPoolById($id: ID!) {
|
||||||
|
pool(id: $id) {
|
||||||
|
id,
|
||||||
|
sqrtPrice,
|
||||||
|
tick,
|
||||||
|
totalValueLockedUSD
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Getting Pool(s) filtered by tokens.
|
||||||
|
export const queryPoolsByTokens = gql`
|
||||||
|
query queryPoolsByTokens($tokens: [String!]) {
|
||||||
|
pools(where: { token0_in: $tokens, token1_in: $tokens }) {
|
||||||
|
id,
|
||||||
|
feeTier
|
||||||
|
}
|
||||||
|
}`;
|
||||||
|
|
||||||
|
// Getting PoolDayData(s) filtered by pool and ordered by date.
|
||||||
|
export const queryPoolDayData = gql`
|
||||||
|
query queryPoolDayData($first: Int, $orderBy: PoolDayData_orderBy, $orderDirection: OrderDirection, $pool: String) {
|
||||||
|
poolDayDatas(first: $first, orderBy: $orderBy, orderDirection: $orderDirection, where: { pool: $pool }) {
|
||||||
|
id,
|
||||||
|
date,
|
||||||
|
tvlUSD
|
||||||
|
}
|
||||||
|
}`;
|
@ -1 +1,2 @@
|
|||||||
export * from './src/client';
|
export * from './src/client';
|
||||||
|
export * from './src/utils/index';
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { expect, assert } from 'chai';
|
import { expect, assert } from 'chai';
|
||||||
import { ethers, Contract, ContractTransaction, Signer, constants } from 'ethers';
|
import { ethers, Contract, ContractTransaction, Signer, constants } from 'ethers';
|
||||||
import 'reflect-metadata';
|
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import { Config, getConfig } from '@vulcanize/util';
|
import { Config, getConfig, deployTokens, TESTERC20_ABI } from '@vulcanize/util';
|
||||||
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
||||||
import { getCache } from '@vulcanize/cache';
|
import { getCache } from '@vulcanize/cache';
|
||||||
import { EthClient } from '@vulcanize/ipld-eth-client';
|
import { EthClient } from '@vulcanize/ipld-eth-client';
|
||||||
@ -43,10 +42,6 @@ import {
|
|||||||
checkDecreaseLiquidityEvent,
|
checkDecreaseLiquidityEvent,
|
||||||
checksCollectEvent
|
checksCollectEvent
|
||||||
} from '../test/utils';
|
} from '../test/utils';
|
||||||
import {
|
|
||||||
abi as TESTERC20_ABI,
|
|
||||||
bytecode as TESTERC20_BYTECODE
|
|
||||||
} from '../artifacts/test/contracts/TestERC20.sol/TestERC20.json';
|
|
||||||
import {
|
import {
|
||||||
abi as TESTUNISWAPV3CALLEE_ABI,
|
abi as TESTUNISWAPV3CALLEE_ABI,
|
||||||
bytecode as TESTUNISWAPV3CALLEE_BYTECODE
|
bytecode as TESTUNISWAPV3CALLEE_BYTECODE
|
||||||
@ -56,6 +51,8 @@ import {
|
|||||||
bytecode as WETH9_BYTECODE
|
bytecode as WETH9_BYTECODE
|
||||||
} from '../artifacts/test/contracts/WETH9.sol/WETH9.json';
|
} from '../artifacts/test/contracts/WETH9.sol/WETH9.json';
|
||||||
|
|
||||||
|
const NETWORK_RPC_URL = 'http://localhost:8545';
|
||||||
|
|
||||||
const TICK_MIN = -887272;
|
const TICK_MIN = -887272;
|
||||||
const TICK_MAX = 887272;
|
const TICK_MAX = 887272;
|
||||||
const getMinTick = (tickSpacing: number) => Math.ceil(TICK_MIN / tickSpacing) * tickSpacing;
|
const getMinTick = (tickSpacing: number) => Math.ceil(TICK_MIN / tickSpacing) * tickSpacing;
|
||||||
@ -119,7 +116,7 @@ describe('uni-watcher', () => {
|
|||||||
gqlSubscriptionEndpoint
|
gqlSubscriptionEndpoint
|
||||||
});
|
});
|
||||||
|
|
||||||
const provider = new ethers.providers.JsonRpcProvider('http://localhost:8545');
|
const provider = new ethers.providers.JsonRpcProvider(NETWORK_RPC_URL);
|
||||||
signer = provider.getSigner();
|
signer = provider.getSigner();
|
||||||
recipient = await signer.getAddress();
|
recipient = await signer.getAddress();
|
||||||
});
|
});
|
||||||
@ -147,15 +144,10 @@ describe('uni-watcher', () => {
|
|||||||
|
|
||||||
it('should deploy 2 tokens', async () => {
|
it('should deploy 2 tokens', async () => {
|
||||||
// Deploy 2 tokens.
|
// Deploy 2 tokens.
|
||||||
const Token = new ethers.ContractFactory(TESTERC20_ABI, TESTERC20_BYTECODE, signer);
|
|
||||||
|
|
||||||
// Not initializing global token contract variables just yet; initialized in `create pool` to maintatin order coherency.
|
// Not initializing global token contract variables just yet; initialized in `create pool` to maintatin order coherency.
|
||||||
const token0 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
|
({ token0Address, token1Address } = await deployTokens(signer));
|
||||||
token0Address = token0.address;
|
|
||||||
expect(token0Address).to.not.be.empty;
|
expect(token0Address).to.not.be.empty;
|
||||||
|
|
||||||
const token1 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
|
|
||||||
token1Address = token1.address;
|
|
||||||
expect(token1Address).to.not.be.empty;
|
expect(token1Address).to.not.be.empty;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
|
|
||||||
import { Database } from '../database';
|
import { Database } from '../database';
|
||||||
|
import { Client as UniClient } from '../client';
|
||||||
|
|
||||||
export async function watchContract (db: Database, address: string, kind: string, startingBlock: number): Promise<void> {
|
export async function watchContract (db: Database, address: string, kind: string, startingBlock: number): Promise<void> {
|
||||||
// Always use the checksum address (https://docs.ethers.io/v5/api/utils/address/#utils-getAddress).
|
// Always use the checksum address (https://docs.ethers.io/v5/api/utils/address/#utils-getAddress).
|
||||||
@ -8,3 +9,22 @@ export async function watchContract (db: Database, address: string, kind: string
|
|||||||
|
|
||||||
await db.saveContract(contractAddress, kind, startingBlock);
|
await db.saveContract(contractAddress, kind, startingBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const watchEvent = async (uniClient: UniClient, eventType: string): Promise<any> => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
(async () => {
|
||||||
|
try {
|
||||||
|
const subscription = await uniClient.watchEvents((value: any) => {
|
||||||
|
if (value.event.__typename === eventType) {
|
||||||
|
if (subscription) {
|
||||||
|
subscription.unsubscribe();
|
||||||
|
}
|
||||||
|
resolve(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
reject(error);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import { ethers, utils, Contract, Signer, BigNumber, ContractTransaction } from 'ethers';
|
import { ethers, utils, Contract, Signer } from 'ethers';
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
|
||||||
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
import { Client as UniClient } from '@vulcanize/uni-watcher';
|
||||||
|
import { createPool, initializePool } from '@vulcanize/util';
|
||||||
|
|
||||||
// https://github.com/ethers-io/ethers.js/issues/195
|
// https://github.com/ethers-io/ethers.js/issues/195
|
||||||
export function linkLibraries (
|
export const linkLibraries = (
|
||||||
{
|
{
|
||||||
bytecode,
|
bytecode,
|
||||||
linkReferences
|
linkReferences
|
||||||
@ -13,7 +14,7 @@ export function linkLibraries (
|
|||||||
bytecode: string
|
bytecode: string
|
||||||
linkReferences: { [fileName: string]: { [contractName: string]: { length: number; start: number }[] } }
|
linkReferences: { [fileName: string]: { [contractName: string]: { length: number; start: number }[] } }
|
||||||
},
|
},
|
||||||
libraries: { [libraryName: string]: string }): string {
|
libraries: { [libraryName: string]: string }): string => {
|
||||||
Object.keys(linkReferences).forEach((fileName) => {
|
Object.keys(linkReferences).forEach((fileName) => {
|
||||||
Object.keys(linkReferences[fileName]).forEach((contractName) => {
|
Object.keys(linkReferences[fileName]).forEach((contractName) => {
|
||||||
if (!libraries.hasOwnProperty(contractName)) {
|
if (!libraries.hasOwnProperty(contractName)) {
|
||||||
@ -31,16 +32,16 @@ export function linkLibraries (
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
return bytecode;
|
return bytecode;
|
||||||
}
|
};
|
||||||
|
|
||||||
export async function testCreatePool (
|
export const testCreatePool = async (
|
||||||
uniClient: UniClient,
|
uniClient: UniClient,
|
||||||
factory: Contract,
|
factory: Contract,
|
||||||
token0Address: string,
|
token0Address: string,
|
||||||
token1Address: string,
|
token1Address: string,
|
||||||
fee: number,
|
fee: number,
|
||||||
poolAbi: any,
|
poolAbi: any,
|
||||||
signer: Signer): Promise<Contract> {
|
signer: Signer): Promise<Contract> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
@ -60,20 +61,19 @@ export async function testCreatePool (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Create pool.
|
// Create pool.
|
||||||
const transaction: ContractTransaction = await factory.createPool(token0Address, token1Address, fee);
|
await createPool(factory, token0Address, token1Address, fee);
|
||||||
await transaction.wait();
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
export function testInitialize (
|
export const testInitialize = async (
|
||||||
uniClient: UniClient,
|
uniClient: UniClient,
|
||||||
pool: Contract,
|
pool: Contract,
|
||||||
sqrtPrice: string,
|
sqrtPrice: string,
|
||||||
tick: number): Promise<void> {
|
tick: number): Promise<void> => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
(async () => {
|
(async () => {
|
||||||
@ -92,30 +92,29 @@ export function testInitialize (
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Pool initialize.
|
// Pool initialize.
|
||||||
const transaction: ContractTransaction = await pool.initialize(BigNumber.from(sqrtPrice));
|
await initializePool(pool, sqrtPrice);
|
||||||
await transaction.wait();
|
|
||||||
})();
|
})();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
function checkEventCommonValues (value: any, expectedContract: string) {
|
const checkEventCommonValues = (value: any, expectedContract: string) => {
|
||||||
expect(value.block).to.not.be.empty;
|
expect(value.block).to.not.be.empty;
|
||||||
expect(value.tx).to.not.be.empty;
|
expect(value.tx).to.not.be.empty;
|
||||||
expect(value.contract).to.equal(expectedContract);
|
expect(value.contract).to.equal(expectedContract);
|
||||||
expect(value.eventIndex).to.be.a('number');
|
expect(value.eventIndex).to.be.a('number');
|
||||||
|
|
||||||
expect(value.proof).to.not.be.empty;
|
expect(value.proof).to.not.be.empty;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkPoolCreatedEvent (
|
export const checkPoolCreatedEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
token0Address: string,
|
token0Address: string,
|
||||||
token1Address: string,
|
token1Address: string,
|
||||||
fee: number): string {
|
fee: number): string => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('PoolCreatedEvent');
|
expect(value.event.__typename).to.equal('PoolCreatedEvent');
|
||||||
@ -126,28 +125,28 @@ export function checkPoolCreatedEvent (
|
|||||||
expect(value.event.pool).to.not.be.empty;
|
expect(value.event.pool).to.not.be.empty;
|
||||||
|
|
||||||
return value.event.pool;
|
return value.event.pool;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkInitializeEvent (
|
export const checkInitializeEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
sqrtPrice: string,
|
sqrtPrice: string,
|
||||||
tick: number): void {
|
tick: number): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('InitializeEvent');
|
expect(value.event.__typename).to.equal('InitializeEvent');
|
||||||
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
|
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
|
||||||
expect(value.event.tick).to.equal(tick.toString());
|
expect(value.event.tick).to.equal(tick.toString());
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkMintEvent (
|
export const checkMintEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
expectedSender: string,
|
expectedSender: string,
|
||||||
exptectedOwner: string,
|
exptectedOwner: string,
|
||||||
tickLower: number,
|
tickLower: number,
|
||||||
tickUpper: number,
|
tickUpper: number,
|
||||||
amount: number): void {
|
amount: number): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('MintEvent');
|
expect(value.event.__typename).to.equal('MintEvent');
|
||||||
@ -158,15 +157,15 @@ export function checkMintEvent (
|
|||||||
expect(value.event.amount).to.equal(amount.toString());
|
expect(value.event.amount).to.equal(amount.toString());
|
||||||
expect(value.event.amount0).to.not.be.empty;
|
expect(value.event.amount0).to.not.be.empty;
|
||||||
expect(value.event.amount1).to.not.be.empty;
|
expect(value.event.amount1).to.not.be.empty;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkBurnEvent (
|
export const checkBurnEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
exptectedOwner: string,
|
exptectedOwner: string,
|
||||||
tickLower: number,
|
tickLower: number,
|
||||||
tickUpper: number,
|
tickUpper: number,
|
||||||
amount: number): void {
|
amount: number): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('BurnEvent');
|
expect(value.event.__typename).to.equal('BurnEvent');
|
||||||
@ -176,16 +175,16 @@ export function checkBurnEvent (
|
|||||||
expect(value.event.amount).to.equal(amount.toString());
|
expect(value.event.amount).to.equal(amount.toString());
|
||||||
expect(value.event.amount0).to.not.be.empty;
|
expect(value.event.amount0).to.not.be.empty;
|
||||||
expect(value.event.amount1).to.not.be.empty;
|
expect(value.event.amount1).to.not.be.empty;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkSwapEvent (
|
export const checkSwapEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
expectedSender: string,
|
expectedSender: string,
|
||||||
recipient: string,
|
recipient: string,
|
||||||
sqrtPrice: string,
|
sqrtPrice: string,
|
||||||
tick: number
|
tick: number
|
||||||
): void {
|
): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('SwapEvent');
|
expect(value.event.__typename).to.equal('SwapEvent');
|
||||||
@ -196,40 +195,40 @@ export function checkSwapEvent (
|
|||||||
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
|
expect(value.event.sqrtPriceX96).to.equal(sqrtPrice);
|
||||||
expect(value.event.liquidity).to.not.be.empty;
|
expect(value.event.liquidity).to.not.be.empty;
|
||||||
expect(value.event.tick).to.equal(tick.toString());
|
expect(value.event.tick).to.equal(tick.toString());
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkTransferEvent (
|
export const checkTransferEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
from: string,
|
from: string,
|
||||||
recipient: string
|
recipient: string
|
||||||
): void {
|
): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('TransferEvent');
|
expect(value.event.__typename).to.equal('TransferEvent');
|
||||||
expect(value.event.from).to.equal(from);
|
expect(value.event.from).to.equal(from);
|
||||||
expect(value.event.to).to.equal(recipient);
|
expect(value.event.to).to.equal(recipient);
|
||||||
expect(value.event.tokenId).to.equal('1');
|
expect(value.event.tokenId).to.equal('1');
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkIncreaseLiquidityEvent (
|
export const checkIncreaseLiquidityEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
amount1Desired: number
|
amount1Desired: number
|
||||||
): void {
|
): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.tokenId).to.equal('1');
|
expect(value.event.tokenId).to.equal('1');
|
||||||
expect(value.event.liquidity).to.equal(amount1Desired.toString());
|
expect(value.event.liquidity).to.equal(amount1Desired.toString());
|
||||||
expect(value.event.amount0).to.equal(amount1Desired.toString());
|
expect(value.event.amount0).to.equal(amount1Desired.toString());
|
||||||
expect(value.event.amount1).to.equal(amount1Desired.toString());
|
expect(value.event.amount1).to.equal(amount1Desired.toString());
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checkDecreaseLiquidityEvent (
|
export const checkDecreaseLiquidityEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
liquidity: number
|
liquidity: number
|
||||||
): void {
|
): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('DecreaseLiquidityEvent');
|
expect(value.event.__typename).to.equal('DecreaseLiquidityEvent');
|
||||||
@ -237,13 +236,13 @@ export function checkDecreaseLiquidityEvent (
|
|||||||
expect(value.event.liquidity).to.equal(liquidity.toString());
|
expect(value.event.liquidity).to.equal(liquidity.toString());
|
||||||
expect(value.event.amount0).to.not.be.empty;
|
expect(value.event.amount0).to.not.be.empty;
|
||||||
expect(value.event.amount1).to.not.be.empty;
|
expect(value.event.amount1).to.not.be.empty;
|
||||||
}
|
};
|
||||||
|
|
||||||
export function checksCollectEvent (
|
export const checksCollectEvent = (
|
||||||
value: any,
|
value: any,
|
||||||
expectedContract: string,
|
expectedContract: string,
|
||||||
recipient: string
|
recipient: string
|
||||||
): void {
|
): void => {
|
||||||
checkEventCommonValues(value, expectedContract);
|
checkEventCommonValues(value, expectedContract);
|
||||||
|
|
||||||
expect(value.event.__typename).to.equal('CollectEvent');
|
expect(value.event.__typename).to.equal('CollectEvent');
|
||||||
@ -251,4 +250,4 @@ export function checksCollectEvent (
|
|||||||
expect(value.event.recipient).to.equal(recipient);
|
expect(value.event.recipient).to.equal(recipient);
|
||||||
expect(value.event.amount0).to.not.be.empty;
|
expect(value.event.amount0).to.not.be.empty;
|
||||||
expect(value.event.amount1).to.not.be.empty;
|
expect(value.event.amount1).to.not.be.empty;
|
||||||
}
|
};
|
||||||
|
10
packages/util/.gitignore
vendored
Normal file
10
packages/util/.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
node_modules/
|
||||||
|
build/
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
|
||||||
|
#Hardhat files
|
||||||
|
cache
|
||||||
|
artifacts
|
18
packages/util/hardhat.config.ts
Normal file
18
packages/util/hardhat.config.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { HardhatUserConfig } from 'hardhat/config';
|
||||||
|
import '@nomiclabs/hardhat-waffle';
|
||||||
|
|
||||||
|
const config: HardhatUserConfig = {
|
||||||
|
defaultNetwork: 'localhost',
|
||||||
|
solidity: {
|
||||||
|
compilers: [
|
||||||
|
{
|
||||||
|
version: '0.7.6'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
paths: {
|
||||||
|
sources: './test/contracts'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
@ -3,3 +3,4 @@ export * from './src/database';
|
|||||||
export * from './src/job-queue';
|
export * from './src/job-queue';
|
||||||
export * from './src/constants';
|
export * from './src/constants';
|
||||||
export * from './src/index';
|
export * from './src/index';
|
||||||
|
export * from './test/actions';
|
||||||
|
@ -12,10 +12,10 @@
|
|||||||
"toml": "^3.0.0"
|
"toml": "^3.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vulcanize/cache": "^0.1.0",
|
|
||||||
"@types/fs-extra": "^9.0.11",
|
"@types/fs-extra": "^9.0.11",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
"@typescript-eslint/eslint-plugin": "^4.25.0",
|
||||||
"@typescript-eslint/parser": "^4.25.0",
|
"@typescript-eslint/parser": "^4.25.0",
|
||||||
|
"@vulcanize/cache": "^0.1.0",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"eslint": "^7.27.0",
|
"eslint": "^7.27.0",
|
||||||
"eslint-config-semistandard": "^15.0.1",
|
"eslint-config-semistandard": "^15.0.1",
|
||||||
@ -24,11 +24,13 @@
|
|||||||
"eslint-plugin-node": "^11.1.0",
|
"eslint-plugin-node": "^11.1.0",
|
||||||
"eslint-plugin-promise": "^5.1.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"eslint-plugin-standard": "^5.0.0",
|
"eslint-plugin-standard": "^5.0.0",
|
||||||
|
"hardhat": "^2.3.0",
|
||||||
"mocha": "^8.4.0",
|
"mocha": "^8.4.0",
|
||||||
"typeorm": "^0.2.32"
|
"typeorm": "^0.2.32"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
"build": "tsc"
|
"build": "tsc",
|
||||||
|
"test:compile": "hardhat compile"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
packages/util/test/actions.ts
Normal file
34
packages/util/test/actions.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { ethers, Contract, ContractTransaction, Signer, BigNumber } from 'ethers';
|
||||||
|
|
||||||
|
import {
|
||||||
|
abi as TESTERC20_ABI,
|
||||||
|
bytecode as TESTERC20_BYTECODE
|
||||||
|
} from '../artifacts/test/contracts/TestERC20.sol/TestERC20.json';
|
||||||
|
|
||||||
|
export { abi as TESTERC20_ABI } from '../artifacts/test/contracts/TestERC20.sol/TestERC20.json';
|
||||||
|
|
||||||
|
export const deployTokens = async (signer: Signer): Promise<{token0Address: string, token1Address: string}> => {
|
||||||
|
const Token = new ethers.ContractFactory(TESTERC20_ABI, TESTERC20_BYTECODE, signer);
|
||||||
|
|
||||||
|
const token0 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
|
||||||
|
const token0Address = token0.address;
|
||||||
|
|
||||||
|
const token1 = await Token.deploy(ethers.BigNumber.from(2).pow(255));
|
||||||
|
const token1Address = token1.address;
|
||||||
|
|
||||||
|
return { token0Address, token1Address };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createPool = async (
|
||||||
|
factory: Contract,
|
||||||
|
token0Address: string,
|
||||||
|
token1Address: string,
|
||||||
|
fee: number): Promise<void> => {
|
||||||
|
const transaction: ContractTransaction = await factory.createPool(token0Address, token1Address, fee);
|
||||||
|
await transaction.wait();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const initializePool = async (pool: Contract, sqrtPrice: string): Promise<void> => {
|
||||||
|
const transaction: ContractTransaction = await pool.initialize(BigNumber.from(sqrtPrice));
|
||||||
|
await transaction.wait();
|
||||||
|
};
|
@ -72,6 +72,6 @@
|
|||||||
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
"forceConsistentCasingInFileNames": true, /* Disallow inconsistently-cased references to the same file. */
|
||||||
"resolveJsonModule": true /* Enabling the option allows importing JSON, and validating the types in that JSON file. */
|
"resolveJsonModule": true /* Enabling the option allows importing JSON, and validating the types in that JSON file. */
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src", "test"],
|
||||||
"exclude": ["dist"]
|
"exclude": ["dist"]
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user