Commit 8da04505 authored by Mark Tyneway's avatar Mark Tyneway

core-utils: more flexible watcher

Adds new config options to the watcher to allow it to upgrade in
a non breaking way. New config options include setting a global
`pollForPending` and `blocksToFetch`. It is also possible to
specify the number of blocks to fetch on each `Layer`.

The event ids are precomputed and held as globals instead of computed
on the fly each time.
parent 34927928
---
'@eth-optimism/core-utils': minor
---
Allow a configurable L1 and L2 blocks to fetch in the watcher
......@@ -2,9 +2,14 @@
import { ethers } from 'ethers'
import { Provider, TransactionReceipt } from '@ethersproject/abstract-provider'
const SENT_MESSAGE = ethers.utils.id('SentMessage(bytes)')
const RELAYED_MESSAGE = ethers.utils.id(`RelayedMessage(bytes32)`)
const FAILED_RELAYED_MESSAGE = ethers.utils.id(`FailedRelayedMessage(bytes32)`)
export interface Layer {
provider: Provider
messengerAddress: string
blocksToFetch?: number
}
export interface WatcherOptions {
......@@ -12,6 +17,7 @@ export interface WatcherOptions {
l2: Layer
pollInterval?: number
blocksToFetch?: number
pollForPending?: boolean
}
export class Watcher {
......@@ -19,16 +25,20 @@ export class Watcher {
public l2: Layer
public pollInterval = 3000
public blocksToFetch = 1500
public pollForPending = true
constructor(opts: WatcherOptions) {
this.l1 = opts.l1
this.l2 = opts.l2
if (opts.pollInterval) {
if (typeof opts.pollInterval === 'number') {
this.pollInterval = opts.pollInterval
}
if (opts.blocksToFetch) {
if (typeof opts.blocksToFetch === 'number') {
this.blocksToFetch = opts.blocksToFetch
}
if (typeof opts.pollForPending === 'boolean') {
this.pollForPending = opts.pollForPending
}
}
public async getMessageHashesFromL1Tx(l1TxHash: string): Promise<string[]> {
......@@ -40,14 +50,14 @@ export class Watcher {
public async getL1TransactionReceipt(
l2ToL1MsgHash: string,
pollForPending = true
pollForPending?
): Promise<TransactionReceipt> {
return this.getTransactionReceipt(this.l1, l2ToL1MsgHash, pollForPending)
}
public async getL2TransactionReceipt(
l1ToL2MsgHash: string,
pollForPending = true
pollForPending?
): Promise<TransactionReceipt> {
return this.getTransactionReceipt(this.l2, l1ToL2MsgHash, pollForPending)
}
......@@ -65,7 +75,7 @@ export class Watcher {
for (const log of receipt.logs) {
if (
log.address === layer.messengerAddress &&
log.topics[0] === ethers.utils.id('SentMessage(bytes)')
log.topics[0] === SENT_MESSAGE
) {
const [message] = ethers.utils.defaultAbiCoder.decode(
['bytes'],
......@@ -80,22 +90,31 @@ export class Watcher {
public async getTransactionReceipt(
layer: Layer,
msgHash: string,
pollForPending = true
pollForPending?
): Promise<TransactionReceipt> {
if (typeof pollForPending !== 'boolean') {
pollForPending = this.pollForPending
}
let matches: ethers.providers.Log[] = []
let blocksToFetch = layer.blocksToFetch
if (typeof blocksToFetch !== 'number') {
blocksToFetch = this.blocksToFetch
}
// scan for transaction with specified message
while (matches.length === 0) {
const blockNumber = await layer.provider.getBlockNumber()
const startingBlock = Math.max(blockNumber - this.blocksToFetch, 0)
const startingBlock = Math.max(blockNumber - blocksToFetch, 0)
const successFilter: ethers.providers.Filter = {
address: layer.messengerAddress,
topics: [ethers.utils.id(`RelayedMessage(bytes32)`)],
topics: [RELAYED_MESSAGE],
fromBlock: startingBlock,
}
const failureFilter: ethers.providers.Filter = {
address: layer.messengerAddress,
topics: [ethers.utils.id(`FailedRelayedMessage(bytes32)`)],
topics: [FAILED_RELAYED_MESSAGE],
fromBlock: startingBlock,
}
const successLogs = await layer.provider.getLogs(successFilter)
......
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