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::{
49 Error, Metadata,
50 config::{Config, HashFor},
51 error::MetadataError,
52};
53
54pub fn decode_from<T: Config>(event_bytes: Vec<u8>, metadata: Metadata) -> Events<T> {
58 Events::decode_from(event_bytes, metadata)
59}
60
61pub trait StaticEvent: DecodeAsFields {
68 const PALLET: &'static str;
70 const EVENT: &'static str;
72
73 fn is_event(pallet: &str, event: &str) -> bool {
75 Self::PALLET == pallet && Self::EVENT == event
76 }
77}
78
79#[derive_where(Clone)]
82pub struct Events<T> {
83 metadata: Metadata,
84 event_bytes: Arc<[u8]>,
88 start_idx: usize,
89 num_events: u32,
90 marker: core::marker::PhantomData<T>,
91}
92
93impl<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 pub fn decode_from(event_bytes: Vec<u8>, metadata: Metadata) -> Self {
107 let cursor = &mut &*event_bytes;
114 let num_events = <Compact<u32>>::decode(cursor).unwrap_or(Compact(0)).0;
115
116 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 pub fn len(&self) -> u32 {
130 self.num_events
131 }
132
133 pub fn is_empty(&self) -> bool {
136 self.num_events == 0
137 }
138
139 pub fn bytes(&self) -> &[u8] {
141 &self.event_bytes
142 }
143
144 pub fn iter(
150 &self,
151 ) -> impl Iterator<Item = Result<EventDetails<T>, Error>> + Send + Sync + 'static {
152 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 pos += event_details.bytes().len();
167 index += 1;
169 Some(Ok(event_details))
171 }
172 Err(e) => {
173 pos = event_bytes.len();
177 Some(Err(e))
178 }
179 }
180 }
181 })
182 }
183
184 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 pub fn find_first<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
195 self.find::<Ev>().next().transpose()
196 }
197
198 pub fn find_last<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
201 self.find::<Ev>().last().transpose()
202 }
203
204 pub fn has<Ev: StaticEvent>(&self) -> Result<bool, Error> {
206 Ok(self.find::<Ev>().next().transpose()?.is_some())
207 }
208}
209
210#[derive(Copy, Clone, Debug, Eq, PartialEq, Decode, Encode)]
212pub enum Phase {
213 ApplyExtrinsic(u32),
215 Finalization,
217 Initialization,
219}
220
221#[derive(Debug, Clone)]
223pub struct EventDetails<T: Config> {
224 phase: Phase,
225 index: u32,
227 all_bytes: Arc<[u8]>,
228 start_idx: usize,
230 event_start_idx: usize,
232 event_fields_start_idx: usize,
234 event_fields_end_idx: usize,
236 end_idx: usize,
238 metadata: Metadata,
239 topics: Vec<HashFor<T>>,
240}
241
242impl<T: Config> EventDetails<T> {
243 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 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 for field_metadata in &event_variant.fields {
274 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 let event_fields_end_idx = all_bytes.len() - input.len();
286
287 let topics = Vec::<HashFor<T>>::decode(input)?;
289
290 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 pub fn phase(&self) -> Phase {
309 self.phase
310 }
311
312 pub fn index(&self) -> u32 {
314 self.index
315 }
316
317 pub fn pallet_index(&self) -> u8 {
319 self.all_bytes[self.event_fields_start_idx - 2]
322 }
323
324 pub fn variant_index(&self) -> u8 {
326 self.all_bytes[self.event_fields_start_idx - 1]
329 }
330
331 pub fn pallet_name(&self) -> &str {
333 self.event_metadata().pallet.name()
334 }
335
336 pub fn variant_name(&self) -> &str {
338 &self.event_metadata().variant.name
339 }
340
341 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 pub fn bytes(&self) -> &[u8] {
360 &self.all_bytes[self.start_idx..self.end_idx]
361 }
362
363 pub fn field_bytes(&self) -> &[u8] {
365 &self.all_bytes[self.event_fields_start_idx..self.event_fields_end_idx]
366 }
367
368 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 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 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 pub fn topics(&self) -> &[HashFor<T>] {
421 &self.topics
422 }
423}
424
425pub struct EventMetadataDetails<'a> {
427 pub pallet: PalletMetadata<'a>,
429 pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
431}
432
433#[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 #[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 #[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 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 pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
487 EventRecord::new(phase, event, vec![])
488 }
489
490 pub fn metadata<E: TypeInfo + 'static>() -> Metadata {
493 #[allow(unused)]
498 #[derive(TypeInfo)]
499 struct ExtrinsicType<Call> {
500 call: Call,
501 }
502 #[allow(unused)]
505 #[derive(TypeInfo)]
506 enum RuntimeCall {
507 PalletName(Pallet),
508 }
509 #[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 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 pub fn events_raw(
576 metadata: Metadata,
577 event_bytes: Vec<u8>,
578 num_events: u32,
579 ) -> Events<SubstrateConfig> {
580 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 fn metadata<E: TypeInfo + 'static>() -> Metadata {
602 test_utils::metadata::<E>()
603 }
604
605 #[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 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 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 let metadata = metadata::<Event>();
651
652 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 let decoded_event = ev
668 .as_root_event::<AllEvents<Event>>()
669 .expect("can decode event into root enum again");
670
671 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 let metadata = metadata::<Event>();
684
685 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 let metadata = metadata::<Event>();
723
724 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 let metadata = metadata::<Event>();
790
791 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 event_bytes.extend_from_slice(&[3, 127, 45, 0, 2]);
798
799 let events = events_raw(
802 metadata,
803 event_bytes,
804 3, );
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 assert!(events_iter.next().unwrap().is_err());
835 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 let metadata = metadata::<Event>();
849
850 let events = events::<Event>(
853 metadata,
854 vec![event_record(Phase::Finalization, Event::A(1))],
855 );
856
857 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 let metadata = metadata::<Event>();
886
887 let events = events::<Event>(
890 metadata,
891 vec![event_record(
892 Phase::Finalization,
893 Event::A(CompactWrapper(1)),
894 )],
895 );
896
897 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)] 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 let metadata = metadata::<Event>();
930
931 let events = events::<Event>(
934 metadata,
935 vec![event_record(Phase::Finalization, Event::A(MyType::B))],
936 );
937
938 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 let metadata = metadata::<Event>();
964
965 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}