1use 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
50pub fn decode_from<T: Config>(event_bytes: Vec<u8>, metadata: Metadata) -> Events<T> {
54 Events::decode_from(event_bytes, metadata)
55}
56
57pub trait StaticEvent: DecodeAsFields {
64 const PALLET: &'static str;
66 const EVENT: &'static str;
68
69 fn is_event(pallet: &str, event: &str) -> bool {
71 Self::PALLET == pallet && Self::EVENT == event
72 }
73}
74
75#[derive_where(Clone)]
78pub struct Events<T> {
79 metadata: Metadata,
80 event_bytes: Arc<[u8]>,
84 start_idx: usize,
85 num_events: u32,
86 marker: core::marker::PhantomData<T>,
87}
88
89impl<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 pub fn decode_from(event_bytes: Vec<u8>, metadata: Metadata) -> Self {
103 let cursor = &mut &*event_bytes;
110 let num_events = <Compact<u32>>::decode(cursor).unwrap_or(Compact(0)).0;
111
112 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 pub fn len(&self) -> u32 {
126 self.num_events
127 }
128
129 pub fn is_empty(&self) -> bool {
132 self.num_events == 0
133 }
134
135 pub fn bytes(&self) -> &[u8] {
137 &self.event_bytes
138 }
139
140 pub fn iter(
146 &self,
147 ) -> impl Iterator<Item = Result<EventDetails<T>, Error>> + Send + Sync + 'static {
148 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 pos += event_details.bytes().len();
163 index += 1;
165 Some(Ok(event_details))
167 }
168 Err(e) => {
169 pos = event_bytes.len();
173 Some(Err(e))
174 }
175 }
176 }
177 })
178 }
179
180 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 pub fn find_first<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
191 self.find::<Ev>().next().transpose()
192 }
193
194 pub fn find_last<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
197 self.find::<Ev>().last().transpose()
198 }
199
200 pub fn has<Ev: StaticEvent>(&self) -> Result<bool, Error> {
202 Ok(self.find::<Ev>().next().transpose()?.is_some())
203 }
204}
205
206#[derive(Copy, Clone, Debug, Eq, PartialEq, Decode, Encode)]
208pub enum Phase {
209 ApplyExtrinsic(u32),
211 Finalization,
213 Initialization,
215}
216
217#[derive(Debug, Clone)]
219pub struct EventDetails<T: Config> {
220 phase: Phase,
221 index: u32,
223 all_bytes: Arc<[u8]>,
224 start_idx: usize,
226 event_start_idx: usize,
228 event_fields_start_idx: usize,
230 event_fields_end_idx: usize,
232 end_idx: usize,
234 metadata: Metadata,
235 topics: Vec<T::Hash>,
236}
237
238impl<T: Config> EventDetails<T> {
239 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 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 for field_metadata in &event_variant.fields {
270 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 let event_fields_end_idx = all_bytes.len() - input.len();
282
283 let topics = Vec::<T::Hash>::decode(input)?;
285
286 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 pub fn phase(&self) -> Phase {
305 self.phase
306 }
307
308 pub fn index(&self) -> u32 {
310 self.index
311 }
312
313 pub fn pallet_index(&self) -> u8 {
315 self.all_bytes[self.event_fields_start_idx - 2]
318 }
319
320 pub fn variant_index(&self) -> u8 {
322 self.all_bytes[self.event_fields_start_idx - 1]
325 }
326
327 pub fn pallet_name(&self) -> &str {
329 self.event_metadata().pallet.name()
330 }
331
332 pub fn variant_name(&self) -> &str {
334 &self.event_metadata().variant.name
335 }
336
337 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 pub fn bytes(&self) -> &[u8] {
356 &self.all_bytes[self.start_idx..self.end_idx]
357 }
358
359 pub fn field_bytes(&self) -> &[u8] {
361 &self.all_bytes[self.event_fields_start_idx..self.event_fields_end_idx]
362 }
363
364 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 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 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 pub fn topics(&self) -> &[T::Hash] {
417 &self.topics
418 }
419}
420
421pub struct EventMetadataDetails<'a> {
423 pub pallet: PalletMetadata<'a>,
425 pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
427}
428
429#[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 #[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 #[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 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 pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
483 EventRecord::new(phase, event, vec![])
484 }
485
486 pub fn metadata<E: TypeInfo + 'static>() -> Metadata {
489 #[allow(unused)]
494 #[derive(TypeInfo)]
495 struct ExtrinsicType<Call> {
496 call: Call,
497 }
498 #[allow(unused)]
501 #[derive(TypeInfo)]
502 enum RuntimeCall {
503 PalletName(Pallet),
504 }
505 #[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 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 pub fn events_raw(
572 metadata: Metadata,
573 event_bytes: Vec<u8>,
574 num_events: u32,
575 ) -> Events<SubstrateConfig> {
576 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 fn metadata<E: TypeInfo + 'static>() -> Metadata {
598 test_utils::metadata::<E>()
599 }
600
601 #[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 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 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 let metadata = metadata::<Event>();
647
648 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 let decoded_event = ev
664 .as_root_event::<AllEvents<Event>>()
665 .expect("can decode event into root enum again");
666
667 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 let metadata = metadata::<Event>();
680
681 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 let metadata = metadata::<Event>();
719
720 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 let metadata = metadata::<Event>();
786
787 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 event_bytes.extend_from_slice(&[3, 127, 45, 0, 2]);
794
795 let events = events_raw(
798 metadata,
799 event_bytes,
800 3, );
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 assert!(events_iter.next().unwrap().is_err());
831 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 let metadata = metadata::<Event>();
845
846 let events = events::<Event>(
849 metadata,
850 vec![event_record(Phase::Finalization, Event::A(1))],
851 );
852
853 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 let metadata = metadata::<Event>();
882
883 let events = events::<Event>(
886 metadata,
887 vec![event_record(
888 Phase::Finalization,
889 Event::A(CompactWrapper(1)),
890 )],
891 );
892
893 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)] 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 let metadata = metadata::<Event>();
926
927 let events = events::<Event>(
930 metadata,
931 vec![event_record(Phase::Finalization, Event::A(MyType::B))],
932 );
933
934 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 let metadata = metadata::<Event>();
960
961 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}