63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
|
import { ContractEvent } from "./ContractEvent"
|
||
|
import ContractBase from "./contracts/ContractBase"
|
||
|
|
||
|
import { Instantiable, InstantiableConfig } from "../Instantiable.abstract"
|
||
|
|
||
|
export class EventHandler extends Instantiable {
|
||
|
private events = new Set<(blockNumber) => void>()
|
||
|
private lastBlock: number
|
||
|
private interval = 200
|
||
|
private polling: boolean = false
|
||
|
private lastTimeout: NodeJS.Timeout
|
||
|
|
||
|
get count() {
|
||
|
return this.events.size
|
||
|
}
|
||
|
|
||
|
constructor(config: InstantiableConfig) {
|
||
|
super()
|
||
|
this.setInstanceConfig(config)
|
||
|
}
|
||
|
|
||
|
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 = setTimeout(() => this.checkBlock(true, n++), this.interval)
|
||
|
}
|
||
|
|
||
|
public subscribe(callback: (number) => void) {
|
||
|
this.events.add(callback)
|
||
|
this.checkBlock()
|
||
|
|
||
|
return {
|
||
|
unsubscribe: () => this.unsubscribe(callback),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public unsubscribe(callback: (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)
|
||
|
}
|
||
|
}
|