@@ -239,11 +239,17 @@ func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc
239
239
return & rpc.Subscription {}, rpc .ErrNotificationsUnsupported
240
240
}
241
241
242
- rpcSub := notifier .CreateSubscription ()
242
+ var (
243
+ rpcSub = notifier .CreateSubscription ()
244
+ matchedLogs = make (chan []Log )
245
+ )
246
+
247
+ logsSub , err := api .events .SubscribeLogs (crit , matchedLogs )
248
+ if err != nil {
249
+ return nil , err
250
+ }
243
251
244
252
go func () {
245
- matchedLogs := make (chan []Log )
246
- logsSub := api .events .SubscribeLogs (crit , matchedLogs )
247
253
248
254
for {
249
255
select {
@@ -276,18 +282,20 @@ type FilterCriteria struct {
276
282
// used to retrieve logs when the state changes. This method cannot be
277
283
// used to fetch logs that are already stored in the state.
278
284
//
285
+ // Default criteria for the from and to block are "latest".
286
+ // Using "latest" as block number will return logs for mined blocks.
287
+ // Using "pending" as block number returns logs for not yet mined (pending) blocks.
288
+ // In case logs are removed (chain reorg) previously returned logs are returned
289
+ // again but with the removed property set to true.
290
+ //
291
+ // In case "fromBlock" > "toBlock" an error is returned.
292
+ //
279
293
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_newfilter
280
- func (api * PublicFilterAPI ) NewFilter (crit FilterCriteria ) rpc.ID {
281
- var (
282
- logs = make (chan []Log )
283
- logsSub = api .events .SubscribeLogs (crit , logs )
284
- )
285
-
286
- if crit .FromBlock == nil {
287
- crit .FromBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
288
- }
289
- if crit .ToBlock == nil {
290
- crit .ToBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
294
+ func (api * PublicFilterAPI ) NewFilter (crit FilterCriteria ) (rpc.ID , error ) {
295
+ logs := make (chan []Log )
296
+ logsSub , err := api .events .SubscribeLogs (crit , logs )
297
+ if err != nil {
298
+ return rpc .ID ("" ), err
291
299
}
292
300
293
301
api .filtersMu .Lock ()
@@ -312,7 +320,7 @@ func (api *PublicFilterAPI) NewFilter(crit FilterCriteria) rpc.ID {
312
320
}
313
321
}()
314
322
315
- return logsSub .ID
323
+ return logsSub .ID , nil
316
324
}
317
325
318
326
// GetLogs returns logs matching the given argument that are stored within the state.
@@ -363,28 +371,38 @@ func (api *PublicFilterAPI) GetFilterLogs(ctx context.Context, id rpc.ID) ([]Log
363
371
api .filtersMu .Unlock ()
364
372
365
373
if ! found || f .typ != LogsSubscription {
366
- return [] Log {}, nil
374
+ return nil , fmt . Errorf ( "filter not found" )
367
375
}
368
376
369
377
filter := New (api .backend , api .useMipMap )
370
- filter .SetBeginBlock (f .crit .FromBlock .Int64 ())
371
- filter .SetEndBlock (f .crit .ToBlock .Int64 ())
378
+ if f .crit .FromBlock != nil {
379
+ filter .SetBeginBlock (f .crit .FromBlock .Int64 ())
380
+ } else {
381
+ filter .SetBeginBlock (rpc .LatestBlockNumber .Int64 ())
382
+ }
383
+ if f .crit .ToBlock != nil {
384
+ filter .SetEndBlock (f .crit .ToBlock .Int64 ())
385
+ } else {
386
+ filter .SetEndBlock (rpc .LatestBlockNumber .Int64 ())
387
+ }
372
388
filter .SetAddresses (f .crit .Addresses )
373
389
filter .SetTopics (f .crit .Topics )
374
390
375
- logs , err := filter .Find (ctx )
376
- return returnLogs (logs ), err
391
+ logs , err := filter .Find (ctx )
392
+ if err != nil {
393
+ return nil , err
394
+ }
395
+ return returnLogs (logs ), nil
377
396
}
378
397
379
398
// GetFilterChanges returns the logs for the filter with the given id since
380
399
// last time is was called. This can be used for polling.
381
400
//
382
401
// For pending transaction and block filters the result is []common.Hash.
383
- // (pending)Log filters return []Log. If the filter could not be found
384
- // []interface{}{} is returned.
402
+ // (pending)Log filters return []Log.
385
403
//
386
404
// https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_getfilterchanges
387
- func (api * PublicFilterAPI ) GetFilterChanges (id rpc.ID ) interface {} {
405
+ func (api * PublicFilterAPI ) GetFilterChanges (id rpc.ID ) ( interface {}, error ) {
388
406
api .filtersMu .Lock ()
389
407
defer api .filtersMu .Unlock ()
390
408
@@ -400,15 +418,15 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) interface{} {
400
418
case PendingTransactionsSubscription , BlocksSubscription :
401
419
hashes := f .hashes
402
420
f .hashes = nil
403
- return returnHashes (hashes )
404
- case PendingLogsSubscription , LogsSubscription :
421
+ return returnHashes (hashes ), nil
422
+ case LogsSubscription :
405
423
logs := f .logs
406
424
f .logs = nil
407
- return returnLogs (logs )
425
+ return returnLogs (logs ), nil
408
426
}
409
427
}
410
428
411
- return []interface {}{}
429
+ return []interface {}{}, fmt . Errorf ( "filter not found" )
412
430
}
413
431
414
432
// returnHashes is a helper that will return an empty hash array case the given hash array is nil,
@@ -443,15 +461,11 @@ func (args *FilterCriteria) UnmarshalJSON(data []byte) error {
443
461
return err
444
462
}
445
463
446
- if raw .From == nil || raw .From .Int64 () < 0 {
447
- args .FromBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
448
- } else {
464
+ if raw .From != nil {
449
465
args .FromBlock = big .NewInt (raw .From .Int64 ())
450
466
}
451
467
452
- if raw .ToBlock == nil || raw .ToBlock .Int64 () < 0 {
453
- args .ToBlock = big .NewInt (rpc .LatestBlockNumber .Int64 ())
454
- } else {
468
+ if raw .ToBlock != nil {
455
469
args .ToBlock = big .NewInt (raw .ToBlock .Int64 ())
456
470
}
457
471
0 commit comments