subxt/events/
events_type.rs

1use crate::{
2    Error, Metadata,
3    config::{Config, HashFor},
4};
5use derive_where::derive_where;
6use scale_decode::DecodeAsType;
7use subxt_core::events::{EventDetails as CoreEventDetails, Events as CoreEvents};
8
9pub use subxt_core::events::{EventMetadataDetails, Phase, StaticEvent};
10
11/// A collection of events obtained from a block, bundled with the necessary
12/// information needed to decode and iterate over them.
13// Dev note: we are just wrapping the subxt_core types here to avoid leaking them
14// in Subxt and map any errors into Subxt errors so that we don't have this part of the
15// API returning a different error type (ie the subxt_core::Error).
16#[derive_where(Clone, Debug)]
17pub struct Events<T> {
18    inner: CoreEvents<T>,
19}
20
21impl<T: Config> Events<T> {
22    /// Create a new [`Events`] instance from the given bytes.
23    pub fn decode_from(event_bytes: Vec<u8>, metadata: Metadata) -> Self {
24        Self {
25            inner: CoreEvents::decode_from(event_bytes, metadata),
26        }
27    }
28
29    /// The number of events.
30    pub fn len(&self) -> u32 {
31        self.inner.len()
32    }
33
34    /// Are there no events in this block?
35    // Note: mainly here to satisfy clippy..
36    pub fn is_empty(&self) -> bool {
37        self.inner.is_empty()
38    }
39
40    /// Return the bytes representing all of the events.
41    pub fn bytes(&self) -> &[u8] {
42        self.inner.bytes()
43    }
44
45    /// Iterate over all of the events, using metadata to dynamically
46    /// decode them as we go, and returning the raw bytes and other associated
47    /// details. If an error occurs, all subsequent iterations return `None`.
48    // Dev note: The returned iterator is 'static + Send so that we can box it up and make
49    // use of it with our `FilterEvents` stuff.
50    pub fn iter(
51        &self,
52    ) -> impl Iterator<Item = Result<EventDetails<T>, Error>> + Send + Sync + 'static {
53        self.inner
54            .iter()
55            .map(|item| item.map(|e| EventDetails { inner: e }).map_err(Into::into))
56    }
57
58    /// Iterate through the events using metadata to dynamically decode and skip
59    /// them, and return only those which should decode to the provided `Ev` type.
60    /// If an error occurs, all subsequent iterations return `None`.
61    pub fn find<Ev: StaticEvent>(&self) -> impl Iterator<Item = Result<Ev, Error>> {
62        self.inner.find::<Ev>().map(|item| item.map_err(Into::into))
63    }
64
65    /// Iterate through the events using metadata to dynamically decode and skip
66    /// them, and return the first event found which decodes to the provided `Ev` type.
67    pub fn find_first<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
68        self.inner.find_first::<Ev>().map_err(Into::into)
69    }
70
71    /// Iterate through the events using metadata to dynamically decode and skip
72    /// them, and return the last event found which decodes to the provided `Ev` type.
73    pub fn find_last<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
74        self.inner.find_last::<Ev>().map_err(Into::into)
75    }
76
77    /// Find an event that decodes to the type provided. Returns true if it was found.
78    pub fn has<Ev: StaticEvent>(&self) -> Result<bool, Error> {
79        self.inner.has::<Ev>().map_err(Into::into)
80    }
81}
82
83/// The event details.
84#[derive(Debug, Clone)]
85pub struct EventDetails<T: Config> {
86    inner: CoreEventDetails<T>,
87}
88
89impl<T: Config> EventDetails<T> {
90    /// When was the event produced?
91    pub fn phase(&self) -> Phase {
92        self.inner.phase()
93    }
94
95    /// What index is this event in the stored events for this block.
96    pub fn index(&self) -> u32 {
97        self.inner.index()
98    }
99
100    /// The index of the pallet that the event originated from.
101    pub fn pallet_index(&self) -> u8 {
102        self.inner.pallet_index()
103    }
104
105    /// The index of the event variant that the event originated from.
106    pub fn variant_index(&self) -> u8 {
107        self.inner.variant_index()
108    }
109
110    /// The name of the pallet from whence the Event originated.
111    pub fn pallet_name(&self) -> &str {
112        self.inner.pallet_name()
113    }
114
115    /// The name of the event (ie the name of the variant that it corresponds to).
116    pub fn variant_name(&self) -> &str {
117        self.inner.variant_name()
118    }
119
120    /// Fetch details from the metadata for this event.
121    pub fn event_metadata(&self) -> EventMetadataDetails {
122        self.inner.event_metadata()
123    }
124
125    /// Return _all_ of the bytes representing this event, which include, in order:
126    /// - The phase.
127    /// - Pallet and event index.
128    /// - Event fields.
129    /// - Event Topics.
130    pub fn bytes(&self) -> &[u8] {
131        self.inner.bytes()
132    }
133
134    /// Return the bytes representing the fields stored in this event.
135    pub fn field_bytes(&self) -> &[u8] {
136        self.inner.field_bytes()
137    }
138
139    /// Decode and provide the event fields back in the form of a [`scale_value::Composite`]
140    /// type which represents the named or unnamed fields that were present in the event.
141    pub fn field_values(&self) -> Result<scale_value::Composite<u32>, Error> {
142        self.inner.field_values().map_err(Into::into)
143    }
144
145    /// Attempt to decode these [`EventDetails`] into a type representing the event fields.
146    /// Such types are exposed in the codegen as `pallet_name::events::EventName` types.
147    pub fn as_event<E: StaticEvent>(&self) -> Result<Option<E>, Error> {
148        self.inner.as_event::<E>().map_err(Into::into)
149    }
150
151    /// Attempt to decode these [`EventDetails`] into a root event type (which includes
152    /// the pallet and event enum variants as well as the event fields). A compatible
153    /// type for this is exposed via static codegen as a root level `Event` type.
154    pub fn as_root_event<E: DecodeAsType>(&self) -> Result<E, Error> {
155        self.inner.as_root_event::<E>().map_err(Into::into)
156    }
157
158    /// Return the topics associated with this event.
159    pub fn topics(&self) -> &[HashFor<T>] {
160        self.inner.topics()
161    }
162}