@@ -15,6 +15,8 @@ import {
15
15
stringToHex ,
16
16
getAddress ,
17
17
zeroAddress ,
18
+ GetFilterLogsReturnType ,
19
+ InferEventName ,
18
20
} from 'viem' ;
19
21
import { stringify } from 'superjson' ;
20
22
import {
@@ -684,4 +686,71 @@ export class ProtocolContracts<
684
686
args : [ id ] ,
685
687
} ) ;
686
688
}
689
+
690
+ /**
691
+ * Subscribes to specific events emitted by the market smart contract.
692
+ *
693
+ * @param eventName - The name of the event to listen for.
694
+ * @param onLogs - Callback function to handle the event logs.
695
+ * @param fromBlock - (Optional) The starting block number for listening to events.
696
+ * @param pollInterval - (Optional) Interval in milliseconds for polling new events.
697
+ * @returns A function to unsubscribe from the event.
698
+ * @template TEventName - Generic type parameter for event name.
699
+ */
700
+ async subscribeMarket < TEventName extends string | undefined = undefined > (
701
+ eventName : InferEventName < typeof marketABI , TEventName > ,
702
+ onLogs : ( logs : GetFilterLogsReturnType < typeof marketABI > ) => void ,
703
+ fromBlock ?: bigint ,
704
+ pollInterval = 1000 ,
705
+ ) : Promise < ( ) => void > {
706
+ let blockNumber = await this . publicClient . getBlockNumber ( ) ;
707
+ let isUnsubscribed = false ;
708
+ let timeoutId : NodeJS . Timeout ;
709
+
710
+ // Use the specified fromBlock or the current block number
711
+ if ( fromBlock && fromBlock < blockNumber ) {
712
+ blockNumber = fromBlock ;
713
+ }
714
+
715
+ // Function to fetch and process logs
716
+ const getLogs = async ( ) => {
717
+ if ( isUnsubscribed ) return ; // Stop if unsubscribed
718
+
719
+ // Create an event filter
720
+ const filter = await this . publicClient . createContractEventFilter ( {
721
+ abi : marketABI ,
722
+ address : this . contracts [ 'market' ] . address ,
723
+ eventName,
724
+ fromBlock : blockNumber ,
725
+ strict : true ,
726
+ } ) ;
727
+
728
+ // Retrieve logs based on the filter
729
+ const logs = await this . publicClient . getFilterLogs ( { filter } ) ;
730
+
731
+ // Process logs and update the block number
732
+ if ( logs . length > 0 ) {
733
+ const maxBlockNumber = logs . reduce (
734
+ ( max , log ) => ( log . blockNumber > max ? log . blockNumber : max ) ,
735
+ BigInt ( 0 ) ,
736
+ ) ;
737
+ blockNumber = maxBlockNumber + BigInt ( 1 ) ;
738
+ onLogs ( logs ) ;
739
+ }
740
+
741
+ // Schedule the next call
742
+ timeoutId = setTimeout ( ( ) => {
743
+ getLogs ( ) . catch ( logger . error ) ;
744
+ } , pollInterval ) ;
745
+ } ;
746
+
747
+ // Initial call to start the polling process
748
+ getLogs ( ) . catch ( logger . error ) ;
749
+
750
+ // Return the unsubscribe function
751
+ return ( ) => {
752
+ isUnsubscribed = true ; // Set the flag to stop further polling
753
+ clearTimeout ( timeoutId ) ; // Clear the timeout to stop scheduled calls
754
+ } ;
755
+ }
687
756
}
0 commit comments