squid-js/src/keeper/EventHandler.ts

74 lines
1.8 KiB
TypeScript

import { ContractEvent } from './ContractEvent'
import ContractBase from './contracts/ContractBase'
import { Instantiable, InstantiableConfig } from '../Instantiable.abstract'
export class EventHandler extends Instantiable {
get count() {
return this.events.size
}
private events = new Set<(blockNumber) => void>()
private lastBlock: number
private interval = 200
private polling: boolean = false
private lastTimeout: NodeJS.Timeout
constructor(config: InstantiableConfig) {
super()
this.setInstanceConfig(config)
}
public subscribe(callback: (blockNumber: number) => void) {
this.events.add(callback)
this.checkBlock()
return {
unsubscribe: () => this.unsubscribe(callback)
}
}
public unsubscribe(callback: (blockNumber: number) => void) {
this.events.delete(callback)
if (!this.count) {
clearTimeout(this.lastTimeout)
delete this.lastBlock
this.polling = false
}
}
public getEvent(
contract: ContractBase,
eventName: string,
filter: { [key: string]: any }
) {
return new ContractEvent(this, contract, eventName, filter)
}
private async checkBlock(isInterval?: boolean, n = 0) {
const blockNumber = await this.web3.eth.getBlockNumber()
if ((this.polling && !isInterval) || !this.count) {
return
}
this.polling = true
if (!this.lastBlock) {
this.lastBlock = blockNumber
}
if (this.lastBlock !== blockNumber) {
this.events.forEach((fn) => fn(this.lastBlock + 1))
this.lastBlock = blockNumber
}
this.lastTimeout = global.setTimeout(
() => this.checkBlock(true, n++),
this.interval
)
}
}