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