OpenZeppelin / OpenZeppelin/Event-Scanner

`latest` and `sync::from_latest` Should Allow Specifying "Anchor Event Filters" To Determine the Starting Point, But Stream Other Events

Open
#184 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

type: feature
Dominant language
Rust
Stars
19
Forks
7
Avg merge
2h 15m
Merged PRs (30d)
4

Description

Users need a way to establish a starting point for an event scanner based on one set of events, but then actually stream a different (or broader) set of events from that starting point forward.

Example API:

// these events are not streamed, only used as a starting point
let anchor_filter = EventFilter::new()
    .contract_address(addr)
    .event(Tracker::SIGNATURE);

// filter the latest 25 events from `anchor_filter`
let mut event_scanner = EventScanner::sync().from_latest(25, anchor_filter);

// Filter for inbox events (these are actually streamed).
let filter = EventFilter::new()
    .contract_address(self.config.inbox_address)
    .event(FirstEvent::SIGNATURE)
    .event(SecondEvent::SIGNATURE);

let mut stream = event_scanner.subscribe(filter);

Expected behavior for the above code:

  1. Scanner finds the 25th most recent Tracker event -> this determines the starting block
  2. Scanner then streams from that block forward:
    1. All FirstEvent events encountered from that point
    2. All SecondEvent events encountered from that point
  3. The initial Tracker events (set in anchor_filter ) are never emitted to the stream

It is important to include Clear documentation explaining the anchor vs stream filter distinction.


One of the users described a use case for this (paraphrasing):

I need to collect the first 100 Proposed events, but while collecting the first 100 Proposed events, I need the scanner to also stream the Proved events (no matter how many there are), and after collecting 100 Proposed events, live-stream both of these two events

The scanner would be configured similar to the previous example above:

let anchor_filter = EventFilter::new()
    .contract_address(addr)
    .event(Proposed::SIGNATURE);

let mut event_scanner = EventScanner::sync().from_latest(100, anchor_filter);

let filter = EventFilter::new()
    .contract_address(self.config.inbox_address)
    .event(Proposed::SIGNATURE)
    .event(Proved::SIGNATURE);

let mut stream = event_scanner.subscribe(filter);

Expected behavior for the above code:

  1. Scanner finds the 100th most recent Proposed event -> this determines the starting block
  2. Scanner then streams from that block forward:
    1. At most 100 Proposed events (since we started from the 100th)
    2. All Proved events encountered from that point

Related #180

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reading the EventScanner::sync, from_latest, subscribe, and EventFilter entry points, then review related issue #180. Implement the distinction between the anchor filter used to choose the starting block and the stream filter used for emitted events, and document that distinction clearly. Done means the stated Proposed/Proved and Tracker/inbox behaviors are covered.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
backend
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.