subxt_core/
events.rs

1// Copyright 2019-2024 Parity Technologies (UK) Ltd.
2// This file is dual-licensed as Apache-2.0 or GPL-3.0.
3// see LICENSE for license details.
4
5//! Decode and work with events.
6//!
7//! # Example
8//!
9//! ```rust
10//! use subxt_macro::subxt;
11//! use subxt_core::config::PolkadotConfig;
12//! use subxt_core::events;
13//! use subxt_core::metadata;
14//!
15//! // If we generate types without `subxt`, we need to point to `::subxt_core`:
16//! #[subxt(
17//!     crate = "::subxt_core",
18//!     runtime_metadata_path = "../artifacts/polkadot_metadata_full.scale",
19//! )]
20//! pub mod polkadot {}
21//!
22//! // Some metadata we'll use to work with storage entries:
23//! let metadata_bytes = include_bytes!("../../artifacts/polkadot_metadata_full.scale");
24//! let metadata = metadata::decode_from(&metadata_bytes[..]).unwrap();
25//!
26//! // Some bytes representing events (located in System.Events storage):
27//! let event_bytes = hex::decode("1c00000000000000a2e9b53d5517020000000100000000000310c96d901d0102000000020000000408d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dbeea5a030000000000000000000000000000020000000402d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48102700000000000000000000000000000000020000000407be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25fbeea5a030000000000000000000000000000020000002100d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27dbeea5a03000000000000000000000000000000000000000000000000000000000000020000000000426df03e00000000").unwrap();
28//!
29//! // We can decode these bytes like so:
30//! let evs = events::decode_from::<PolkadotConfig>(event_bytes, metadata);
31//!
32//! // And then do things like iterate over them and inspect details:
33//! for ev in evs.iter() {
34//!     let ev = ev.unwrap();
35//!     println!("Index: {}", ev.index());
36//!     println!("Name: {}.{}", ev.pallet_name(), ev.variant_name());
37//!     println!("Fields: {:?}", ev.field_values().unwrap());
38//! }
39//! ```
40
41use alloc::sync::Arc;
42use alloc::vec::Vec;
43use codec::{Compact, Decode, Encode};
44use derive_where::derive_where;
45use scale_decode::{DecodeAsFields, DecodeAsType};
46use subxt_metadata::PalletMetadata;
47
48use crate::{error::MetadataError, Config, Error, Metadata};
49
50/// Create a new [`Events`] instance from the given bytes.
51///
52/// This is a shortcut for [`Events::decode_from`].
53pub fn decode_from<T: Config>(event_bytes: Vec<u8>, metadata: Metadata) -> Events<T> {
54    Events::decode_from(event_bytes, metadata)
55}
56
57/// Trait to uniquely identify the events's identity from the runtime metadata.
58///
59/// Generated API structures that represent an event implement this trait.
60///
61/// The trait is utilized to decode emitted events from a block, via obtaining the
62/// form of the `Event` from the metadata.
63pub trait StaticEvent: DecodeAsFields {
64    /// Pallet name.
65    const PALLET: &'static str;
66    /// Event name.
67    const EVENT: &'static str;
68
69    /// Returns true if the given pallet and event names match this event.
70    fn is_event(pallet: &str, event: &str) -> bool {
71        Self::PALLET == pallet && Self::EVENT == event
72    }
73}
74
75/// A collection of events obtained from a block, bundled with the necessary
76/// information needed to decode and iterate over them.
77#[derive_where(Clone)]
78pub struct Events<T> {
79    metadata: Metadata,
80    // Note; raw event bytes are prefixed with a Compact<u32> containing
81    // the number of events to be decoded. The start_idx reflects that, so
82    // that we can skip over those bytes when decoding them
83    event_bytes: Arc<[u8]>,
84    start_idx: usize,
85    num_events: u32,
86    marker: core::marker::PhantomData<T>,
87}
88
89// Ignore the Metadata when debug-logging events; it's big and distracting.
90impl<T> core::fmt::Debug for Events<T> {
91    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
92        f.debug_struct("Events")
93            .field("event_bytes", &self.event_bytes)
94            .field("start_idx", &self.start_idx)
95            .field("num_events", &self.num_events)
96            .finish()
97    }
98}
99
100impl<T: Config> Events<T> {
101    /// Create a new [`Events`] instance from the given bytes.
102    pub fn decode_from(event_bytes: Vec<u8>, metadata: Metadata) -> Self {
103        // event_bytes is a SCALE encoded vector of events. So, pluck the
104        // compact encoded length from the front, leaving the remaining bytes
105        // for our iterating to decode.
106        //
107        // Note: if we get no bytes back, avoid an error reading vec length
108        // and default to 0 events.
109        let cursor = &mut &*event_bytes;
110        let num_events = <Compact<u32>>::decode(cursor).unwrap_or(Compact(0)).0;
111
112        // Start decoding after the compact encoded bytes.
113        let start_idx = event_bytes.len() - cursor.len();
114
115        Self {
116            metadata,
117            event_bytes: event_bytes.into(),
118            start_idx,
119            num_events,
120            marker: core::marker::PhantomData,
121        }
122    }
123
124    /// The number of events.
125    pub fn len(&self) -> u32 {
126        self.num_events
127    }
128
129    /// Are there no events in this block?
130    // Note: mainly here to satisfy clippy.
131    pub fn is_empty(&self) -> bool {
132        self.num_events == 0
133    }
134
135    /// Return the bytes representing all of the events.
136    pub fn bytes(&self) -> &[u8] {
137        &self.event_bytes
138    }
139
140    /// Iterate over all of the events, using metadata to dynamically
141    /// decode them as we go, and returning the raw bytes and other associated
142    /// details. If an error occurs, all subsequent iterations return `None`.
143    // Dev note: The returned iterator is 'static + Send so that we can box it up and make
144    // use of it with our `FilterEvents` stuff.
145    pub fn iter(
146        &self,
147    ) -> impl Iterator<Item = Result<EventDetails<T>, Error>> + Send + Sync + 'static {
148        // The event bytes ignoring the compact encoded length on the front:
149        let event_bytes = self.event_bytes.clone();
150        let metadata = self.metadata.clone();
151        let num_events = self.num_events;
152
153        let mut pos = self.start_idx;
154        let mut index = 0;
155        core::iter::from_fn(move || {
156            if event_bytes.len() <= pos || num_events == index {
157                None
158            } else {
159                match EventDetails::decode_from(metadata.clone(), event_bytes.clone(), pos, index) {
160                    Ok(event_details) => {
161                        // Skip over decoded bytes in next iteration:
162                        pos += event_details.bytes().len();
163                        // Increment the index:
164                        index += 1;
165                        // Return the event details:
166                        Some(Ok(event_details))
167                    }
168                    Err(e) => {
169                        // By setting the position to the "end" of the event bytes,
170                        // the cursor len will become 0 and the iterator will return `None`
171                        // from now on:
172                        pos = event_bytes.len();
173                        Some(Err(e))
174                    }
175                }
176            }
177        })
178    }
179
180    /// Iterate through the events using metadata to dynamically decode and skip
181    /// them, and return only those which should decode to the provided `Ev` type.
182    /// If an error occurs, all subsequent iterations return `None`.
183    pub fn find<Ev: StaticEvent>(&self) -> impl Iterator<Item = Result<Ev, Error>> + '_ {
184        self.iter()
185            .filter_map(|ev| ev.and_then(|ev| ev.as_event::<Ev>()).transpose())
186    }
187
188    /// Iterate through the events using metadata to dynamically decode and skip
189    /// them, and return the first event found which decodes to the provided `Ev` type.
190    pub fn find_first<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
191        self.find::<Ev>().next().transpose()
192    }
193
194    /// Iterate through the events using metadata to dynamically decode and skip
195    /// them, and return the last event found which decodes to the provided `Ev` type.
196    pub fn find_last<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
197        self.find::<Ev>().last().transpose()
198    }
199
200    /// Find an event that decodes to the type provided. Returns true if it was found.
201    pub fn has<Ev: StaticEvent>(&self) -> Result<bool, Error> {
202        Ok(self.find::<Ev>().next().transpose()?.is_some())
203    }
204}
205
206/// A phase of a block's execution.
207#[derive(Copy, Clone, Debug, Eq, PartialEq, Decode, Encode)]
208pub enum Phase {
209    /// Applying an extrinsic.
210    ApplyExtrinsic(u32),
211    /// Finalizing the block.
212    Finalization,
213    /// Initializing the block.
214    Initialization,
215}
216
217/// The event details.
218#[derive(Debug, Clone)]
219pub struct EventDetails<T: Config> {
220    phase: Phase,
221    /// The index of the event in the list of events in a given block.
222    index: u32,
223    all_bytes: Arc<[u8]>,
224    // start of the bytes (phase, pallet/variant index and then fields and then topic to follow).
225    start_idx: usize,
226    // start of the event (ie pallet/variant index and then the fields and topic after).
227    event_start_idx: usize,
228    // start of the fields (ie after phase and pallet/variant index).
229    event_fields_start_idx: usize,
230    // end of the fields.
231    event_fields_end_idx: usize,
232    // end of everything (fields + topics)
233    end_idx: usize,
234    metadata: Metadata,
235    topics: Vec<T::Hash>,
236}
237
238impl<T: Config> EventDetails<T> {
239    /// Attempt to dynamically decode a single event from our events input.
240    fn decode_from(
241        metadata: Metadata,
242        all_bytes: Arc<[u8]>,
243        start_idx: usize,
244        index: u32,
245    ) -> Result<EventDetails<T>, Error> {
246        let input = &mut &all_bytes[start_idx..];
247
248        let phase = Phase::decode(input)?;
249
250        let event_start_idx = all_bytes.len() - input.len();
251
252        let pallet_index = u8::decode(input)?;
253        let variant_index = u8::decode(input)?;
254
255        let event_fields_start_idx = all_bytes.len() - input.len();
256
257        // Get metadata for the event:
258        let event_pallet = metadata.pallet_by_index_err(pallet_index)?;
259        let event_variant = event_pallet
260            .event_variant_by_index(variant_index)
261            .ok_or(MetadataError::VariantIndexNotFound(variant_index))?;
262        tracing::debug!(
263            "Decoding Event '{}::{}'",
264            event_pallet.name(),
265            &event_variant.name
266        );
267
268        // Skip over the bytes belonging to this event.
269        for field_metadata in &event_variant.fields {
270            // Skip over the bytes for this field:
271            scale_decode::visitor::decode_with_visitor(
272                input,
273                field_metadata.ty.id,
274                metadata.types(),
275                scale_decode::visitor::IgnoreVisitor::new(),
276            )
277            .map_err(scale_decode::Error::from)?;
278        }
279
280        // the end of the field bytes.
281        let event_fields_end_idx = all_bytes.len() - input.len();
282
283        // topics come after the event data in EventRecord.
284        let topics = Vec::<T::Hash>::decode(input)?;
285
286        // what bytes did we skip over in total, including topics.
287        let end_idx = all_bytes.len() - input.len();
288
289        Ok(EventDetails {
290            phase,
291            index,
292            start_idx,
293            event_start_idx,
294            event_fields_start_idx,
295            event_fields_end_idx,
296            end_idx,
297            all_bytes,
298            metadata,
299            topics,
300        })
301    }
302
303    /// When was the event produced?
304    pub fn phase(&self) -> Phase {
305        self.phase
306    }
307
308    /// What index is this event in the stored events for this block.
309    pub fn index(&self) -> u32 {
310        self.index
311    }
312
313    /// The index of the pallet that the event originated from.
314    pub fn pallet_index(&self) -> u8 {
315        // Note: never panics; we expect these bytes to exist
316        // in order that the EventDetails could be created.
317        self.all_bytes[self.event_fields_start_idx - 2]
318    }
319
320    /// The index of the event variant that the event originated from.
321    pub fn variant_index(&self) -> u8 {
322        // Note: never panics; we expect these bytes to exist
323        // in order that the EventDetails could be created.
324        self.all_bytes[self.event_fields_start_idx - 1]
325    }
326
327    /// The name of the pallet from whence the Event originated.
328    pub fn pallet_name(&self) -> &str {
329        self.event_metadata().pallet.name()
330    }
331
332    /// The name of the event (ie the name of the variant that it corresponds to).
333    pub fn variant_name(&self) -> &str {
334        &self.event_metadata().variant.name
335    }
336
337    /// Fetch details from the metadata for this event.
338    pub fn event_metadata(&self) -> EventMetadataDetails {
339        let pallet = self
340            .metadata
341            .pallet_by_index(self.pallet_index())
342            .expect("event pallet to be found; we did this already during decoding");
343        let variant = pallet
344            .event_variant_by_index(self.variant_index())
345            .expect("event variant to be found; we did this already during decoding");
346
347        EventMetadataDetails { pallet, variant }
348    }
349
350    /// Return _all_ of the bytes representing this event, which include, in order:
351    /// - The phase.
352    /// - Pallet and event index.
353    /// - Event fields.
354    /// - Event Topics.
355    pub fn bytes(&self) -> &[u8] {
356        &self.all_bytes[self.start_idx..self.end_idx]
357    }
358
359    /// Return the bytes representing the fields stored in this event.
360    pub fn field_bytes(&self) -> &[u8] {
361        &self.all_bytes[self.event_fields_start_idx..self.event_fields_end_idx]
362    }
363
364    /// Decode and provide the event fields back in the form of a [`scale_value::Composite`]
365    /// type which represents the named or unnamed fields that were present in the event.
366    pub fn field_values(&self) -> Result<scale_value::Composite<u32>, Error> {
367        let bytes = &mut self.field_bytes();
368        let event_metadata = self.event_metadata();
369
370        let mut fields = event_metadata
371            .variant
372            .fields
373            .iter()
374            .map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
375
376        let decoded =
377            scale_value::scale::decode_as_fields(bytes, &mut fields, self.metadata.types())?;
378
379        Ok(decoded)
380    }
381
382    /// Attempt to decode these [`EventDetails`] into a type representing the event fields.
383    /// Such types are exposed in the codegen as `pallet_name::events::EventName` types.
384    pub fn as_event<E: StaticEvent>(&self) -> Result<Option<E>, Error> {
385        let ev_metadata = self.event_metadata();
386        if ev_metadata.pallet.name() == E::PALLET && ev_metadata.variant.name == E::EVENT {
387            let mut fields = ev_metadata
388                .variant
389                .fields
390                .iter()
391                .map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
392            let decoded =
393                E::decode_as_fields(&mut self.field_bytes(), &mut fields, self.metadata.types())?;
394            Ok(Some(decoded))
395        } else {
396            Ok(None)
397        }
398    }
399
400    /// Attempt to decode these [`EventDetails`] into a root event type (which includes
401    /// the pallet and event enum variants as well as the event fields). A compatible
402    /// type for this is exposed via static codegen as a root level `Event` type.
403    pub fn as_root_event<E: DecodeAsType>(&self) -> Result<E, Error> {
404        let bytes = &self.all_bytes[self.event_start_idx..self.event_fields_end_idx];
405
406        let decoded = E::decode_as_type(
407            &mut &bytes[..],
408            self.metadata.outer_enums().event_enum_ty(),
409            self.metadata.types(),
410        )?;
411
412        Ok(decoded)
413    }
414
415    /// Return the topics associated with this event.
416    pub fn topics(&self) -> &[T::Hash] {
417        &self.topics
418    }
419}
420
421/// Details for the given event plucked from the metadata.
422pub struct EventMetadataDetails<'a> {
423    /// Metadata for the pallet that the event belongs to.
424    pub pallet: PalletMetadata<'a>,
425    /// Metadata for the variant which describes the pallet events.
426    pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
427}
428
429/// Event related test utilities used outside this module.
430#[cfg(test)]
431pub(crate) mod test_utils {
432    use super::*;
433    use crate::config::{Config, SubstrateConfig};
434    use codec::Encode;
435    use frame_metadata::{
436        v15::{
437            CustomMetadata, ExtrinsicMetadata, OuterEnums, PalletEventMetadata, PalletMetadata,
438            RuntimeMetadataV15,
439        },
440        RuntimeMetadataPrefixed,
441    };
442    use scale_info::{meta_type, TypeInfo};
443
444    /// An "outer" events enum containing exactly one event.
445    #[derive(
446        Encode,
447        Decode,
448        TypeInfo,
449        Clone,
450        Debug,
451        PartialEq,
452        Eq,
453        scale_encode::EncodeAsType,
454        scale_decode::DecodeAsType,
455    )]
456    pub enum AllEvents<Ev> {
457        Test(Ev),
458    }
459
460    /// This encodes to the same format an event is expected to encode to
461    /// in node System.Events storage.
462    #[derive(Encode)]
463    pub struct EventRecord<E: Encode> {
464        phase: Phase,
465        event: AllEvents<E>,
466        topics: Vec<<SubstrateConfig as Config>::Hash>,
467    }
468
469    impl<E: Encode> EventRecord<E> {
470        /// Create a new event record with the given phase, event, and topics.
471        pub fn new(phase: Phase, event: E, topics: Vec<<SubstrateConfig as Config>::Hash>) -> Self {
472            Self {
473                phase,
474                event: AllEvents::Test(event),
475                topics,
476            }
477        }
478    }
479
480    /// Build an EventRecord, which encoded events in the format expected
481    /// to be handed back from storage queries to System.Events.
482    pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
483        EventRecord::new(phase, event, vec![])
484    }
485
486    /// Build fake metadata consisting of a single pallet that knows
487    /// about the event type provided.
488    pub fn metadata<E: TypeInfo + 'static>() -> Metadata {
489        // Extrinsic needs to contain at least the generic type parameter "Call"
490        // for the metadata to be valid.
491        // The "Call" type from the metadata is used to decode extrinsics.
492        // In reality, the extrinsic type has "Call", "Address", "Extra", "Signature" generic types.
493        #[allow(unused)]
494        #[derive(TypeInfo)]
495        struct ExtrinsicType<Call> {
496            call: Call,
497        }
498        // Because this type is used to decode extrinsics, we expect this to be a TypeDefVariant.
499        // Each pallet must contain one single variant.
500        #[allow(unused)]
501        #[derive(TypeInfo)]
502        enum RuntimeCall {
503            PalletName(Pallet),
504        }
505        // The calls of the pallet.
506        #[allow(unused)]
507        #[derive(TypeInfo)]
508        enum Pallet {
509            #[allow(unused)]
510            SomeCall,
511        }
512
513        let pallets = vec![PalletMetadata {
514            name: "Test",
515            storage: None,
516            calls: None,
517            event: Some(PalletEventMetadata {
518                ty: meta_type::<E>(),
519            }),
520            constants: vec![],
521            error: None,
522            index: 0,
523            docs: vec![],
524        }];
525
526        let extrinsic = ExtrinsicMetadata {
527            version: 0,
528            signed_extensions: vec![],
529            address_ty: meta_type::<()>(),
530            call_ty: meta_type::<RuntimeCall>(),
531            signature_ty: meta_type::<()>(),
532            extra_ty: meta_type::<()>(),
533        };
534
535        let meta = RuntimeMetadataV15::new(
536            pallets,
537            extrinsic,
538            meta_type::<()>(),
539            vec![],
540            OuterEnums {
541                call_enum_ty: meta_type::<()>(),
542                event_enum_ty: meta_type::<AllEvents<E>>(),
543                error_enum_ty: meta_type::<()>(),
544            },
545            CustomMetadata {
546                map: Default::default(),
547            },
548        );
549        let runtime_metadata: RuntimeMetadataPrefixed = meta.into();
550        let metadata: subxt_metadata::Metadata = runtime_metadata.try_into().unwrap();
551
552        Metadata::from(metadata)
553    }
554
555    /// Build an `Events` object for test purposes, based on the details provided,
556    /// and with a default block hash.
557    pub fn events<E: Decode + Encode>(
558        metadata: Metadata,
559        event_records: Vec<EventRecord<E>>,
560    ) -> Events<SubstrateConfig> {
561        let num_events = event_records.len() as u32;
562        let mut event_bytes = Vec::new();
563        for ev in event_records {
564            ev.encode_to(&mut event_bytes);
565        }
566        events_raw(metadata, event_bytes, num_events)
567    }
568
569    /// Much like [`events`], but takes pre-encoded events and event count, so that we can
570    /// mess with the bytes in tests if we need to.
571    pub fn events_raw(
572        metadata: Metadata,
573        event_bytes: Vec<u8>,
574        num_events: u32,
575    ) -> Events<SubstrateConfig> {
576        // Prepend compact encoded length to event bytes:
577        let mut all_event_bytes = Compact(num_events).encode();
578        all_event_bytes.extend(event_bytes);
579        Events::decode_from(all_event_bytes, metadata)
580    }
581}
582
583#[cfg(test)]
584mod tests {
585    use super::{
586        test_utils::{event_record, events, events_raw, AllEvents, EventRecord},
587        *,
588    };
589    use crate::config::SubstrateConfig;
590    use crate::events::Phase;
591    use codec::Encode;
592    use primitive_types::H256;
593    use scale_info::TypeInfo;
594    use scale_value::Value;
595
596    /// Build a fake wrapped metadata.
597    fn metadata<E: TypeInfo + 'static>() -> Metadata {
598        test_utils::metadata::<E>()
599    }
600
601    /// [`RawEventDetails`] can be annoying to test, because it contains
602    /// type info in the decoded field Values. Strip that here so that
603    /// we can compare fields more easily.
604    #[derive(Debug, PartialEq, Eq, Clone)]
605    pub struct TestRawEventDetails {
606        pub phase: Phase,
607        pub index: u32,
608        pub pallet: String,
609        pub pallet_index: u8,
610        pub variant: String,
611        pub variant_index: u8,
612        pub fields: Vec<scale_value::Value>,
613    }
614
615    /// Compare some actual [`RawEventDetails`] with a hand-constructed
616    /// (probably) [`TestRawEventDetails`].
617    pub fn assert_raw_events_match(
618        actual: EventDetails<SubstrateConfig>,
619        expected: TestRawEventDetails,
620    ) {
621        let actual_fields_no_context: Vec<_> = actual
622            .field_values()
623            .expect("can decode field values (2)")
624            .into_values()
625            .map(|value| value.remove_context())
626            .collect();
627
628        // Check each of the other fields:
629        assert_eq!(actual.phase(), expected.phase);
630        assert_eq!(actual.index(), expected.index);
631        assert_eq!(actual.pallet_name(), expected.pallet);
632        assert_eq!(actual.pallet_index(), expected.pallet_index);
633        assert_eq!(actual.variant_name(), expected.variant);
634        assert_eq!(actual.variant_index(), expected.variant_index);
635        assert_eq!(actual_fields_no_context, expected.fields);
636    }
637
638    #[test]
639    fn statically_decode_single_root_event() {
640        #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo, scale_decode::DecodeAsType)]
641        enum Event {
642            A(u8, bool, Vec<String>),
643        }
644
645        // Create fake metadata that knows about our single event, above:
646        let metadata = metadata::<Event>();
647
648        // Encode our events in the format we expect back from a node, and
649        // construst an Events object to iterate them:
650        let event = Event::A(1, true, vec!["Hi".into()]);
651        let events = events::<Event>(
652            metadata,
653            vec![event_record(Phase::ApplyExtrinsic(123), event.clone())],
654        );
655
656        let ev = events
657            .iter()
658            .next()
659            .expect("one event expected")
660            .expect("event should be extracted OK");
661
662        // This is the line we're testing:
663        let decoded_event = ev
664            .as_root_event::<AllEvents<Event>>()
665            .expect("can decode event into root enum again");
666
667        // It should equal the event we put in:
668        assert_eq!(decoded_event, AllEvents::Test(event));
669    }
670
671    #[test]
672    fn dynamically_decode_single_event() {
673        #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
674        enum Event {
675            A(u8, bool, Vec<String>),
676        }
677
678        // Create fake metadata that knows about our single event, above:
679        let metadata = metadata::<Event>();
680
681        // Encode our events in the format we expect back from a node, and
682        // construst an Events object to iterate them:
683        let event = Event::A(1, true, vec!["Hi".into()]);
684        let events = events::<Event>(
685            metadata,
686            vec![event_record(Phase::ApplyExtrinsic(123), event)],
687        );
688
689        let mut event_details = events.iter();
690        assert_raw_events_match(
691            event_details.next().unwrap().unwrap(),
692            TestRawEventDetails {
693                phase: Phase::ApplyExtrinsic(123),
694                index: 0,
695                pallet: "Test".to_string(),
696                pallet_index: 0,
697                variant: "A".to_string(),
698                variant_index: 0,
699                fields: vec![
700                    Value::u128(1),
701                    Value::bool(true),
702                    Value::unnamed_composite(vec![Value::string("Hi")]),
703                ],
704            },
705        );
706        assert!(event_details.next().is_none());
707    }
708
709    #[test]
710    fn dynamically_decode_multiple_events() {
711        #[derive(Clone, Copy, Debug, PartialEq, Decode, Encode, TypeInfo)]
712        enum Event {
713            A(u8),
714            B(bool),
715        }
716
717        // Create fake metadata that knows about our single event, above:
718        let metadata = metadata::<Event>();
719
720        // Encode our events in the format we expect back from a node, and
721        // construst an Events object to iterate them:
722        let event1 = Event::A(1);
723        let event2 = Event::B(true);
724        let event3 = Event::A(234);
725
726        let events = events::<Event>(
727            metadata,
728            vec![
729                event_record(Phase::Initialization, event1),
730                event_record(Phase::ApplyExtrinsic(123), event2),
731                event_record(Phase::Finalization, event3),
732            ],
733        );
734
735        let mut event_details = events.iter();
736
737        assert_raw_events_match(
738            event_details.next().unwrap().unwrap(),
739            TestRawEventDetails {
740                index: 0,
741                phase: Phase::Initialization,
742                pallet: "Test".to_string(),
743                pallet_index: 0,
744                variant: "A".to_string(),
745                variant_index: 0,
746                fields: vec![Value::u128(1)],
747            },
748        );
749        assert_raw_events_match(
750            event_details.next().unwrap().unwrap(),
751            TestRawEventDetails {
752                index: 1,
753                phase: Phase::ApplyExtrinsic(123),
754                pallet: "Test".to_string(),
755                pallet_index: 0,
756                variant: "B".to_string(),
757                variant_index: 1,
758                fields: vec![Value::bool(true)],
759            },
760        );
761        assert_raw_events_match(
762            event_details.next().unwrap().unwrap(),
763            TestRawEventDetails {
764                index: 2,
765                phase: Phase::Finalization,
766                pallet: "Test".to_string(),
767                pallet_index: 0,
768                variant: "A".to_string(),
769                variant_index: 0,
770                fields: vec![Value::u128(234)],
771            },
772        );
773        assert!(event_details.next().is_none());
774    }
775
776    #[test]
777    fn dynamically_decode_multiple_events_until_error() {
778        #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
779        enum Event {
780            A(u8),
781            B(bool),
782        }
783
784        // Create fake metadata that knows about our single event, above:
785        let metadata = metadata::<Event>();
786
787        // Encode 2 events:
788        let mut event_bytes = vec![];
789        event_record(Phase::Initialization, Event::A(1)).encode_to(&mut event_bytes);
790        event_record(Phase::ApplyExtrinsic(123), Event::B(true)).encode_to(&mut event_bytes);
791
792        // Push a few naff bytes to the end (a broken third event):
793        event_bytes.extend_from_slice(&[3, 127, 45, 0, 2]);
794
795        // Encode our events in the format we expect back from a node, and
796        // construst an Events object to iterate them:
797        let events = events_raw(
798            metadata,
799            event_bytes,
800            3, // 2 "good" events, and then it'll hit the naff bytes.
801        );
802
803        let mut events_iter = events.iter();
804        assert_raw_events_match(
805            events_iter.next().unwrap().unwrap(),
806            TestRawEventDetails {
807                index: 0,
808                phase: Phase::Initialization,
809                pallet: "Test".to_string(),
810                pallet_index: 0,
811                variant: "A".to_string(),
812                variant_index: 0,
813                fields: vec![Value::u128(1)],
814            },
815        );
816        assert_raw_events_match(
817            events_iter.next().unwrap().unwrap(),
818            TestRawEventDetails {
819                index: 1,
820                phase: Phase::ApplyExtrinsic(123),
821                pallet: "Test".to_string(),
822                pallet_index: 0,
823                variant: "B".to_string(),
824                variant_index: 1,
825                fields: vec![Value::bool(true)],
826            },
827        );
828
829        // We'll hit an error trying to decode the third event:
830        assert!(events_iter.next().unwrap().is_err());
831        // ... and then "None" from then on.
832        assert!(events_iter.next().is_none());
833        assert!(events_iter.next().is_none());
834    }
835
836    #[test]
837    fn compact_event_field() {
838        #[derive(Clone, Debug, PartialEq, Encode, Decode, TypeInfo)]
839        enum Event {
840            A(#[codec(compact)] u32),
841        }
842
843        // Create fake metadata that knows about our single event, above:
844        let metadata = metadata::<Event>();
845
846        // Encode our events in the format we expect back from a node, and
847        // construst an Events object to iterate them:
848        let events = events::<Event>(
849            metadata,
850            vec![event_record(Phase::Finalization, Event::A(1))],
851        );
852
853        // Dynamically decode:
854        let mut event_details = events.iter();
855        assert_raw_events_match(
856            event_details.next().unwrap().unwrap(),
857            TestRawEventDetails {
858                index: 0,
859                phase: Phase::Finalization,
860                pallet: "Test".to_string(),
861                pallet_index: 0,
862                variant: "A".to_string(),
863                variant_index: 0,
864                fields: vec![Value::u128(1)],
865            },
866        );
867        assert!(event_details.next().is_none());
868    }
869
870    #[test]
871    fn compact_wrapper_struct_field() {
872        #[derive(Clone, Decode, Debug, PartialEq, Encode, TypeInfo)]
873        enum Event {
874            A(#[codec(compact)] CompactWrapper),
875        }
876
877        #[derive(Clone, Decode, Debug, PartialEq, codec::CompactAs, Encode, TypeInfo)]
878        struct CompactWrapper(u64);
879
880        // Create fake metadata that knows about our single event, above:
881        let metadata = metadata::<Event>();
882
883        // Encode our events in the format we expect back from a node, and
884        // construct an Events object to iterate them:
885        let events = events::<Event>(
886            metadata,
887            vec![event_record(
888                Phase::Finalization,
889                Event::A(CompactWrapper(1)),
890            )],
891        );
892
893        // Dynamically decode:
894        let mut event_details = events.iter();
895        assert_raw_events_match(
896            event_details.next().unwrap().unwrap(),
897            TestRawEventDetails {
898                index: 0,
899                phase: Phase::Finalization,
900                pallet: "Test".to_string(),
901                pallet_index: 0,
902                variant: "A".to_string(),
903                variant_index: 0,
904                fields: vec![Value::unnamed_composite(vec![Value::u128(1)])],
905            },
906        );
907        assert!(event_details.next().is_none());
908    }
909
910    #[test]
911    fn event_containing_explicit_index() {
912        #[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
913        #[repr(u8)]
914        #[allow(trivial_numeric_casts, clippy::unnecessary_cast)] // required because the Encode derive produces a warning otherwise
915        pub enum MyType {
916            B = 10u8,
917        }
918
919        #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
920        enum Event {
921            A(MyType),
922        }
923
924        // Create fake metadata that knows about our single event, above:
925        let metadata = metadata::<Event>();
926
927        // Encode our events in the format we expect back from a node, and
928        // construct an Events object to iterate them:
929        let events = events::<Event>(
930            metadata,
931            vec![event_record(Phase::Finalization, Event::A(MyType::B))],
932        );
933
934        // Dynamically decode:
935        let mut event_details = events.iter();
936        assert_raw_events_match(
937            event_details.next().unwrap().unwrap(),
938            TestRawEventDetails {
939                index: 0,
940                phase: Phase::Finalization,
941                pallet: "Test".to_string(),
942                pallet_index: 0,
943                variant: "A".to_string(),
944                variant_index: 0,
945                fields: vec![Value::unnamed_variant("B", vec![])],
946            },
947        );
948        assert!(event_details.next().is_none());
949    }
950
951    #[test]
952    fn topics() {
953        #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo, scale_decode::DecodeAsType)]
954        enum Event {
955            A(u8, bool, Vec<String>),
956        }
957
958        // Create fake metadata that knows about our single event, above:
959        let metadata = metadata::<Event>();
960
961        // Encode our events in the format we expect back from a node, and
962        // construct an Events object to iterate them:
963        let event = Event::A(1, true, vec!["Hi".into()]);
964        let topics = vec![H256::from_low_u64_le(123), H256::from_low_u64_le(456)];
965        let events = events::<Event>(
966            metadata,
967            vec![EventRecord::new(
968                Phase::ApplyExtrinsic(123),
969                event,
970                topics.clone(),
971            )],
972        );
973
974        let ev = events
975            .iter()
976            .next()
977            .expect("one event expected")
978            .expect("event should be extracted OK");
979
980        assert_eq!(topics, ev.topics());
981    }
982}