@@ -62,6 +62,49 @@ export class FilterService implements IFilterService {
6262 this . supportedTypes = [ constants . FILTER . TYPE . LOG , constants . FILTER . TYPE . NEW_BLOCK ] ;
6363 }
6464
65+ /**
66+ * Generates cache key for filter ID
67+ * @param filterId
68+ * @private
69+ */
70+ private getCacheKey ( filterId : string ) : string {
71+ return `${ constants . CACHE_KEY . FILTERID } _${ filterId } ` ;
72+ }
73+
74+ /**
75+ * Updates filter cache with new data
76+ * @param filterId
77+ * @param type
78+ * @param params
79+ * @param lastQueried
80+ * @param method
81+ * @param requestDetails
82+ * @private
83+ */
84+ private async updateFilterCache (
85+ filterId : string ,
86+ type : string ,
87+ params : any ,
88+ lastQueried : number | null ,
89+ method : string ,
90+ requestDetails : RequestDetails ,
91+ ) : Promise < void > {
92+ const cacheKey = this . getCacheKey ( filterId ) ;
93+ await this . cacheService . set ( cacheKey , { type, params, lastQueried } , method , requestDetails , constants . FILTER . TTL ) ;
94+ }
95+
96+ /**
97+ * Retrieves filter from cache
98+ * @param filterId
99+ * @param method
100+ * @param requestDetails
101+ * @private
102+ */
103+ private async getFilterFromCache ( filterId : string , method : string , requestDetails : RequestDetails ) {
104+ const cacheKey = this . getCacheKey ( filterId ) ;
105+ return await this . cacheService . getAsync ( cacheKey , method , requestDetails ) ;
106+ }
107+
65108 /**
66109 * Creates a new filter with the specified type and parameters
67110 * @param type
@@ -70,20 +113,12 @@ export class FilterService implements IFilterService {
70113 */
71114 async createFilter ( type : string , params : any , requestDetails : RequestDetails ) : Promise < string > {
72115 const filterId = generateRandomHex ( ) ;
73- const cacheKey = `${ constants . CACHE_KEY . FILTERID } _${ filterId } ` ;
74- await this . cacheService . set (
75- cacheKey ,
76- {
77- type,
78- params,
79- lastQueried : null ,
80- } ,
81- this . ethNewFilter ,
82- requestDetails ,
83- constants . FILTER . TTL ,
84- ) ;
116+ await this . updateFilterCache ( filterId , type , params , null , this . ethNewFilter , requestDetails ) ;
117+
85118 if ( this . logger . isLevelEnabled ( 'trace' ) ) {
86- this . logger . trace ( `${ requestDetails . formattedRequestId } created filter with TYPE=${ type } , params: ${ params } ` ) ;
119+ this . logger . trace (
120+ `${ requestDetails . formattedRequestId } created filter with TYPE=${ type } , params: ${ JSON . stringify ( params ) } ` ,
121+ ) ;
87122 }
88123 return filterId ;
89124 }
@@ -130,27 +165,24 @@ export class FilterService implements IFilterService {
130165 }
131166
132167 async newBlockFilter ( requestDetails : RequestDetails ) : Promise < string > {
133- try {
134- FilterService . requireFiltersEnabled ( ) ;
135- return await this . createFilter (
136- constants . FILTER . TYPE . NEW_BLOCK ,
137- {
138- blockAtCreation : await this . common . getLatestBlockNumber ( requestDetails ) ,
139- } ,
140- requestDetails ,
141- ) ;
142- } catch ( e ) {
143- throw this . common . genericErrorHandler ( e ) ;
144- }
168+ FilterService . requireFiltersEnabled ( ) ;
169+
170+ return await this . createFilter (
171+ constants . FILTER . TYPE . NEW_BLOCK ,
172+ {
173+ blockAtCreation : await this . common . getLatestBlockNumber ( requestDetails ) ,
174+ } ,
175+ requestDetails ,
176+ ) ;
145177 }
146178
147179 public async uninstallFilter ( filterId : string , requestDetails : RequestDetails ) : Promise < boolean > {
148180 FilterService . requireFiltersEnabled ( ) ;
149181
150- const cacheKey = `${ constants . CACHE_KEY . FILTERID } _${ filterId } ` ;
151- const filter = await this . cacheService . getAsync ( cacheKey , this . ethUninstallFilter , requestDetails ) ;
182+ const filter = await this . getFilterFromCache ( filterId , this . ethUninstallFilter , requestDetails ) ;
152183
153184 if ( filter ) {
185+ const cacheKey = this . getCacheKey ( filterId ) ;
154186 await this . cacheService . delete ( cacheKey , this . ethUninstallFilter , requestDetails ) ;
155187 return true ;
156188 }
@@ -165,9 +197,8 @@ export class FilterService implements IFilterService {
165197 public async getFilterLogs ( filterId : string , requestDetails : RequestDetails ) : Promise < Log [ ] > {
166198 FilterService . requireFiltersEnabled ( ) ;
167199
168- const cacheKey = `${ constants . CACHE_KEY . FILTERID } _${ filterId } ` ;
169- const filter = await this . cacheService . getAsync ( cacheKey , this . ethGetFilterLogs , requestDetails ) ;
170- if ( filter ?. type != constants . FILTER . TYPE . LOG ) {
200+ const filter = await this . getFilterFromCache ( filterId , this . ethGetFilterLogs , requestDetails ) ;
201+ if ( filter ?. type !== constants . FILTER . TYPE . LOG ) {
171202 throw predefined . FILTER_NOT_FOUND ;
172203 }
173204
@@ -181,82 +212,114 @@ export class FilterService implements IFilterService {
181212 ) ;
182213
183214 // update filter to refresh TTL
184- await this . cacheService . set (
185- cacheKey ,
186- {
187- type : filter . type ,
188- params : filter . params ,
189- lastQueried : filter . lastQueried ,
190- } ,
215+ await this . updateFilterCache (
216+ filterId ,
217+ filter . type ,
218+ filter . params ,
219+ filter . lastQueried ,
191220 this . ethGetFilterChanges ,
192221 requestDetails ,
193- constants . FILTER . TTL ,
194222 ) ;
195223
196224 return logs ;
197225 }
198226
227+ /**
228+ * Handles log filter changes
229+ * @param filter
230+ * @param requestDetails
231+ * @private
232+ */
233+ private async handleLogFilterChanges (
234+ filter : any ,
235+ requestDetails : RequestDetails ,
236+ ) : Promise < { result : Log [ ] ; latestBlockNumber : number } > {
237+ const result = await this . common . getLogs (
238+ null ,
239+ filter ?. lastQueried || filter ?. params . fromBlock ,
240+ filter ?. params . toBlock ,
241+ filter ?. params . address ,
242+ filter ?. params . topics ,
243+ requestDetails ,
244+ ) ;
245+
246+ // get the latest block number and add 1 to exclude current results from the next response because
247+ // the mirror node query executes "gte" not "gt"
248+ const latestBlockNumber =
249+ Number (
250+ result . length ? result [ result . length - 1 ] . blockNumber : await this . common . getLatestBlockNumber ( requestDetails ) ,
251+ ) + 1 ;
252+
253+ return { result, latestBlockNumber } ;
254+ }
255+
256+ /**
257+ * Handles new block filter changes
258+ * @param filter
259+ * @param requestDetails
260+ * @private
261+ */
262+ private async handleNewBlockFilterChanges (
263+ filter : any ,
264+ requestDetails : RequestDetails ,
265+ ) : Promise < { result : string [ ] ; latestBlockNumber : number } > {
266+ const blockResponse = await this . mirrorNodeClient . getBlocks (
267+ requestDetails ,
268+ [ `gt:${ filter . lastQueried || filter . params . blockAtCreation } ` ] ,
269+ undefined ,
270+ {
271+ order : 'asc' ,
272+ } ,
273+ ) ;
274+
275+ const latestBlockNumber = Number (
276+ blockResponse ?. blocks ?. length
277+ ? blockResponse . blocks [ blockResponse . blocks . length - 1 ] . number
278+ : await this . common . getLatestBlockNumber ( requestDetails ) ,
279+ ) ;
280+
281+ const result = blockResponse ?. blocks ?. map ( ( r ) => r . hash ) || [ ] ;
282+
283+ return { result, latestBlockNumber } ;
284+ }
285+
199286 public async getFilterChanges ( filterId : string , requestDetails : RequestDetails ) : Promise < string [ ] | Log [ ] > {
200287 FilterService . requireFiltersEnabled ( ) ;
201288
202- const cacheKey = `${ constants . CACHE_KEY . FILTERID } _${ filterId } ` ;
203- const filter = await this . cacheService . getAsync ( cacheKey , this . ethGetFilterChanges , requestDetails ) ;
289+ const filter = await this . getFilterFromCache ( filterId , this . ethGetFilterChanges , requestDetails ) ;
204290
205291 if ( ! filter ) {
206292 throw predefined . FILTER_NOT_FOUND ;
207293 }
208294
209- let result , latestBlockNumber ;
210- if ( filter . type === constants . FILTER . TYPE . LOG ) {
211- result = await this . common . getLogs (
212- null ,
213- filter ?. lastQueried || filter ?. params . fromBlock ,
214- filter ?. params . toBlock ,
215- filter ?. params . address ,
216- filter ?. params . topics ,
217- requestDetails ,
218- ) ;
295+ let result : string [ ] | Log [ ] ;
296+ let latestBlockNumber : number ;
219297
220- // get the latest block number and add 1 to exclude current results from the next response because
221- // the mirror node query executes "gte" not "gt"
222- latestBlockNumber =
223- Number (
224- result . length
225- ? result [ result . length - 1 ] . blockNumber
226- : await this . common . getLatestBlockNumber ( requestDetails ) ,
227- ) + 1 ;
228- } else if ( filter . type === constants . FILTER . TYPE . NEW_BLOCK ) {
229- result = await this . mirrorNodeClient . getBlocks (
230- requestDetails ,
231- [ `gt:${ filter . lastQueried || filter . params . blockAtCreation } ` ] ,
232- undefined ,
233- {
234- order : 'asc' ,
235- } ,
236- ) ;
237-
238- latestBlockNumber = Number (
239- result ?. blocks ?. length
240- ? result . blocks [ result . blocks . length - 1 ] . number
241- : await this . common . getLatestBlockNumber ( requestDetails ) ,
242- ) ;
243-
244- result = result ?. blocks ?. map ( ( r ) => r . hash ) || [ ] ;
245- } else if ( this . supportedTypes . indexOf ( filter . type ) === - 1 ) {
246- throw predefined . UNSUPPORTED_METHOD ;
298+ switch ( filter . type ) {
299+ case constants . FILTER . TYPE . LOG : {
300+ const logResult = await this . handleLogFilterChanges ( filter , requestDetails ) ;
301+ result = logResult . result ;
302+ latestBlockNumber = logResult . latestBlockNumber ;
303+ break ;
304+ }
305+ case constants . FILTER . TYPE . NEW_BLOCK : {
306+ const blockResult = await this . handleNewBlockFilterChanges ( filter , requestDetails ) ;
307+ result = blockResult . result ;
308+ latestBlockNumber = blockResult . latestBlockNumber ;
309+ break ;
310+ }
311+ default :
312+ throw predefined . UNSUPPORTED_METHOD ;
247313 }
248314
249315 // update filter to refresh TTL and set lastQueried block number
250- await this . cacheService . set (
251- cacheKey ,
252- {
253- type : filter . type ,
254- params : filter . params ,
255- lastQueried : latestBlockNumber ,
256- } ,
316+ await this . updateFilterCache (
317+ filterId ,
318+ filter . type ,
319+ filter . params ,
320+ latestBlockNumber ,
257321 this . ethGetFilterChanges ,
258322 requestDetails ,
259- constants . FILTER . TTL ,
260323 ) ;
261324
262325 return result ;
0 commit comments