Commit 9a5e7ecb authored by Annie Ke's avatar Annie Ke Committed by Kelvin Fichter

feat: add event-indexer script

parent 44d56278
FROM_BLOCK=
TO_BLOCK=
SEQUENCER_URL=
ETH_ADDR=
UNI_FACTORY_ADDR=
BLOCK_INTERVAL=
EVENTS_OUTPUT_PATH=
node_modules/ node_modules/
build/ build/
\ No newline at end of file all-events.json
...@@ -6,23 +6,21 @@ ...@@ -6,23 +6,21 @@
## Getting started ## Getting started
### Building and usage
After cloning and switching to the repository, install dependencies: After cloning and switching to the repository, install dependencies:
```bash ```bash
$ yarn $ yarn
``` ```
Use the following commands to build, use, test, and lint:
```bash
$ yarn build
$ yarn start
$ yarn test
$ yarn lint
```
### Configuration ### Configuration
We're using `dotenv` for our configuration. We're using `dotenv` for our configuration.
To configure the project, clone this repository and copy the `env.example` file to `.env`.
### Runnign scripts
To run an individual script directly:
```bash
$ npx ts-node scripts/event-indexer.ts
```
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
"lint": "yarn run lint:fix && yarn run lint:check", "lint": "yarn run lint:fix && yarn run lint:check",
"lint:fix": "yarn lint:check --fix", "lint:fix": "yarn lint:check --fix",
"lint:check": "eslint .", "lint:check": "eslint .",
"build": "tsc -p tsconfig.build.json",
"pre-commit": "lint-staged" "pre-commit": "lint-staged"
}, },
"devDependencies": { "devDependencies": {
...@@ -19,7 +18,9 @@ ...@@ -19,7 +18,9 @@
"typescript": "^4.3.2" "typescript": "^4.3.2"
}, },
"dependencies": { "dependencies": {
"@discoveryjs/json-ext": "^0.5.3",
"@eth-optimism/contracts": "^0.4.10", "@eth-optimism/contracts": "^0.4.10",
"@uniswap/v3-core-optimism": "^1.0.0-rc.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"ethers": "^5.4.5" "ethers": "^5.4.5"
} }
......
import { Contract, providers, ethers } from 'ethers'
import { createWriteStream } from 'fs'
import dotenv from 'dotenv'
import { stringifyStream } from '@discoveryjs/json-ext'
import { getContractFactory } from '@eth-optimism/contracts'
import { abi as FACTORY_ABI } from '@uniswap/v3-core-optimism/artifacts-ovm/contracts/UniswapV3Factory.sol/UniswapV3Factory.json'
dotenv.config()
const env = process.env
const SEQUENCER_URL = env.SEQUENCER_URL || 'http://localhost:8545'
const ETH_ADDR = env.ETH_ADDR || '0x4200000000000000000000000000000000000006'
const UNI_FACTORY_ADDR =
env.UNI_FACTORY_ADDR || '0x1F98431c8aD98523631AE4a59f267346ea31F984' // address on mainnet
const FROM_BLOCK = env.FROM_BLOCK || '0'
const TO_BLOCK = env.TO_BLOCK || 'latest'
const BLOCK_INTERVAL = parseInt(env.BLOCK_INTERVAL, 10) || 2000
const EVENTS_OUTPUT_PATH = env.EVENTS_OUTPUT_PATH || './all-events.json'
interface FindAllEventsOptions {
provider: providers.StaticJsonRpcProvider
contract: Contract
filter: ethers.EventFilter
fromBlock?: number
toBlock?: number
blockInterval?: number
}
interface AllEventsOutput {
ethTransfers: ethers.Event[]
uniV3FeeAmountEnabled: ethers.Event[]
uniV3PoolCreated: ethers.Event[]
lastBlock: number
}
const findAllEvents = async (
options: FindAllEventsOptions
): Promise<ethers.Event[]> => {
const { provider, contract, filter, fromBlock, toBlock, blockInterval } =
options
const cache = {
startingBlockNumber: fromBlock || 0,
events: [],
}
let events: ethers.Event[] = []
let startingBlockNumber = fromBlock || 0
let endingBlockNumber = toBlock || (await provider.getBlockNumber())
while (startingBlockNumber < endingBlockNumber) {
events = events.concat(
await contract.queryFilter(
filter,
startingBlockNumber, // inclusive of both beginning and end
// https://docs.ethers.io/v5/api/providers/types/#providers-Filter
Math.min(startingBlockNumber + blockInterval - 1, endingBlockNumber)
)
)
if (startingBlockNumber + blockInterval > endingBlockNumber) {
cache.startingBlockNumber = endingBlockNumber
cache.events = cache.events.concat(events)
break
}
startingBlockNumber += blockInterval
endingBlockNumber = await provider.getBlockNumber()
}
return cache.events
}
;(async () => {
console.log('Ready to index events')
const provider = new ethers.providers.StaticJsonRpcProvider(SEQUENCER_URL)
const signer = ethers.Wallet.createRandom().connect(provider)
const ethContract = getContractFactory('OVM_ETH')
.connect(signer)
.attach(ETH_ADDR)
const uniV3FactoryContract = new Contract(
UNI_FACTORY_ADDR,
FACTORY_ABI,
provider
)
let maxBlock
if (TO_BLOCK === 'latest') {
const lastBlock = await provider.getBlock('latest')
maxBlock = lastBlock.number
} else {
maxBlock = parseInt(TO_BLOCK, 10)
}
console.log('Max block:', maxBlock)
const fromBlock = parseInt(FROM_BLOCK, 10)
const [ethTransfers, uniV3FeeAmountEnabled, uniV3PoolCreated] =
await Promise.all([
findAllEvents({
provider,
contract: ethContract,
filter: ethContract.filters.Transfer(),
fromBlock,
toBlock: maxBlock,
blockInterval: BLOCK_INTERVAL,
}),
findAllEvents({
provider,
contract: uniV3FactoryContract,
filter: uniV3FactoryContract.filters.FeeAmountEnabled(),
fromBlock,
toBlock: maxBlock,
blockInterval: BLOCK_INTERVAL,
}),
findAllEvents({
provider,
contract: uniV3FactoryContract,
filter: uniV3FactoryContract.filters.PoolCreated(),
fromBlock,
toBlock: maxBlock,
blockInterval: BLOCK_INTERVAL,
}),
])
console.log(`Found ${ethTransfers.length} ETH transfer events`)
console.log(`Found ${uniV3FeeAmountEnabled.length} FeeAmountEnabled events`)
console.log(`Found ${uniV3PoolCreated.length} PoolCreated events`)
const output: AllEventsOutput = {
lastBlock: maxBlock,
ethTransfers,
uniV3FeeAmountEnabled,
uniV3PoolCreated,
}
console.log('Writing output to file', EVENTS_OUTPUT_PATH)
const writeStream = createWriteStream(EVENTS_OUTPUT_PATH, 'utf-8')
stringifyStream(output, null, 2)
.pipe(writeStream)
.on('error', (error) => console.error(error))
.on('finish', () => console.log('Done writing to json file'))
})().catch((err) => {
console.log(err)
process.exit(1)
})
{ {
"extends": "../../tsconfig.json" "extends": "../../tsconfig.json",
"compilerOptions": {
"resolveJsonModule": true,
}
} }
...@@ -457,6 +457,11 @@ ...@@ -457,6 +457,11 @@
rxjs "^7.2.0" rxjs "^7.2.0"
semver "^7.3.5" semver "^7.3.5"
"@discoveryjs/json-ext@^0.5.3":
version "0.5.3"
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d"
integrity sha512-Fxt+AfXgjMoin2maPIYzFZnQjAXjAL0PHscM5pRTtatFqB+vZxAM9tLp2Optnuw3QOQC40jTNeGYFOMvyf7v9g==
"@ensdomains/ens@^0.4.4": "@ensdomains/ens@^0.4.4":
version "0.4.5" version "0.4.5"
resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc" resolved "https://registry.yarnpkg.com/@ensdomains/ens/-/ens-0.4.5.tgz#e0aebc005afdc066447c6e22feb4eda89a5edbfc"
...@@ -2875,6 +2880,11 @@ ...@@ -2875,6 +2880,11 @@
resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44"
integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==
"@uniswap/v3-core-optimism@^1.0.0-rc.0":
version "1.0.0-rc.0"
resolved "https://registry.yarnpkg.com/@uniswap/v3-core-optimism/-/v3-core-optimism-1.0.0-rc.0.tgz#fafe94c2d435a2133a470fc2793370c544463dd3"
integrity sha512-mJ5TwiWabR02G8lceVc2+3lmFOqVI3p++wpQQcvVHv+pfGq38NSaHbirmGB8sbv7x29wUteiNL7soHoD6tGe7g==
"@yarnpkg/lockfile@^1.1.0": "@yarnpkg/lockfile@^1.1.0":
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment