import { Listener } from '@ethersproject/providers' ; import { useContractLoader } from 'hooks/ContractLoader' ; import { ContractName } from 'models/contract-name' ; import { useEffect , useMemo , useState } from 'react' ; import { readProvider } from 'constants/readProvider' ; export default function useEventListener < E > ( { contractName , eventName , startBlock , topics , includeHistory , } ) { const contracts = useContractLoader ( ) ; const [ events , setEvents ] = useState < ( E & { timestamp : number ; } ) [ ] > ( [ ] ) ; const [ shouldGetHistory , setShouldGetHistory ] = useState < boolean > ( ! ! includeHistory ) ; const provider = readProvider ; const contract = contracts && contractName && contracts [ contractName ] ; const formatEvent = async ( event ) => { const timestamp = ( await event . getBlock ( ) ) . timestamp ; return { ... event . args , timestamp , } ; } ; const eventTopic = contracts && contractName && eventName && contracts [ contractName ] . interface . getEventTopic ( eventName ) ; const filter = useMemo ( ( ) => { return ( contract && eventName && JSON . stringify ( { address : contract . address , topics : [ ... ( eventTopic ? [ eventTopic ] : [ ] ) , ... ( topics ?? [ ] ) ] , } ) ) ; } , [ contract , eventName , eventTopic , topics ] ) ; useEffect ( ( ) => { if ( shouldGetHistory && filter ) { contract ?. queryFilter ( JSON . parse ( filter ) ) . then ( async ( initialEvents ) => { const events = await Promise . all ( initialEvents . slice ( 0 , initialEvents . length - 1 ) . map ( e => formatEvent ( e ) ) . reverse ( ) ) ; setEvents ( events ) ; setShouldGetHistory ( false ) ; } ) ; } } , [ shouldGetHistory , filter , contract ] ) ; useEffect ( ( ) => { if ( provider && startBlock !== undefined ) { provider . resetEventsBlock ( startBlock ) ; } if ( contract && filter ) { try { const filterParsed = JSON . parse ( filter ) ; const listener = async ( ... _events ) => { const event = await formatEvent ( _events [ _events . length - 1 ] ) ; setEvents ( ( events ) => [ event , ... events ] ) ; } ; contract . on ( filterParsed , listener ) ; return ( ) => { contract . off ( filterParsed , listener ) ; } ; } catch ( e ) { console . log ( e ) ; } } } , [ provider , startBlock , contract , eventName , filter ] ) ; return events ; }