Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to filter events to those of a specific type or types #457

Closed
jsdw opened this issue Feb 17, 2022 · 0 comments · Fixed by #461
Closed

Make it easier to filter events to those of a specific type or types #457

jsdw opened this issue Feb 17, 2022 · 0 comments · Fixed by #461
Assignees

Comments

@jsdw
Copy link
Collaborator

jsdw commented Feb 17, 2022

The new evevnt API gives us back a stream of chunks of events, which we can filter and such as we please. A common desire is to be able to filter this stream of events to look for a specific type of events (or perhaps a couple of types.

Currently, you might need to do something like:

let mut transfer_events = api
    .events()
    .subscribe()
    .await?
    // Ignore errors returning events:
    .filter_map(|events| future::ready(events.ok()))
    // Map events to just the one we care about:
    .flat_map(|events| {
        let transfer_events = events
            .find::<polkadot::balances::events::Transfer>()
            .collect::<Vec<_>>();
        stream::iter(transfer_events)
    });

This results in a stream of events of type polkadot::balances::events::Transfer. Aside from being a little verbose, it allocates when it collects these events into a Vec, and it discards errors. And more, if we want to search for more than one type of event, it gets more complex.

It'd be lovely if we instead had an API that could be used like:

let mut transfer_events = api
    .events()
    .subscribe()
    .await?
    .filter_event::<polkadot::balances::events::Transfer>()

This would return something like Result<polkadot::balances::events::Transfer, BasicError>, where an error is returned if we fail to decode an error we expect to be able to decode, or if there is a problem obtaining events for a block.

Using a little trait magic, we may also be able to support something like:

let mut transfer_events = api
    .events()
    .subscribe()
    .await?
    .filter_events::<(polkadot::balances::events::Transfer, polkadot::balances::events::SomeOtherEvent)>()

Which allows us to simultaneously search for and decode multiple events. The return type here would likely be something like Result<(Option<polkadot::balances::events::Transfer>, Option<polkadot::balances::events::SomeOtherEvent>), BasicError>, and this pattern could be extended to tuples of N length. We'd then match on our event tuple to work with them like:

match event {
    (Some(transfer), None) => println!("Transfer succeeded"),
    (None, Some(other)) => println!("Another event found")
}

(I'd guess that filter_event would just delegate to filter_events and call it with a 1-tuple).

This would make it easier to look for specific events, and could also avoid allocating and properly forward errors, unlike the obvious user-space approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant