1use crate::{
12 error::{DispatchError, Error},
13 events::{EventMetadataDetails, RootEvent},
14 metadata::MetadataError,
15 EventDetails, Metadata, Phase, StaticEvent,
16};
17use alloc::{
18 string::{String, ToString},
19 sync::Arc,
20 vec::Vec,
21};
22use codec::{Decode, Encode};
23use log::*;
24use scale_info::PortableRegistry;
25use scale_value::Composite;
26
27#[derive(Debug, Clone, Encode, Decode, PartialEq)]
31pub struct RawEventDetails<Hash: Decode + Encode> {
32 phase: Phase,
33 index: u32,
35 bytes: Vec<u8>,
41 field_bytes: Vec<u8>,
43 pallet_index: u8,
45 pallet_name: String,
46 pallet_bytes: Vec<u8>,
47 variant_index: u8,
49 variant_name: String,
50 topics: Vec<Hash>,
52}
53
54impl<Hash: Encode + Decode> RawEventDetails<Hash> {
55 pub fn phase(&self) -> Phase {
57 self.phase
58 }
59
60 pub fn index(&self) -> u32 {
62 self.index
63 }
64
65 pub fn pallet_index(&self) -> u8 {
67 self.pallet_index
70 }
71
72 pub fn variant_index(&self) -> u8 {
74 self.variant_index
77 }
78
79 pub fn pallet_name(&self) -> &str {
81 &self.pallet_name
82 }
83
84 pub fn variant_name(&self) -> &str {
86 &self.variant_name
87 }
88
89 pub fn event_metadata<'a>(
91 &'a self,
92 metadata: &'a Metadata,
93 ) -> Result<EventMetadataDetails<'a>, Error> {
94 let pallet = metadata
95 .pallet_by_index(self.pallet_index())
96 .ok_or(Error::Metadata(MetadataError::PalletIndexNotFound(self.pallet_index())))?;
97 let variant = pallet
98 .event_variant_by_index(self.variant_index())
99 .ok_or(Error::Metadata(MetadataError::VariantIndexNotFound(self.variant_index())))?;
100 let event_metadata = EventMetadataDetails { pallet, variant };
101 self.metadata_sanity_check(&event_metadata)?;
102 Ok(event_metadata)
103 }
104
105 pub fn bytes(&self) -> &[u8] {
111 &self.bytes
112 }
113
114 pub fn field_bytes(&self) -> &[u8] {
116 &self.field_bytes
117 }
118
119 pub fn field_values(&self, metadata: &Metadata) -> Result<Composite<u32>, Error> {
122 let event_metadata = self.event_metadata(metadata)?;
123 self.field_values_inner(&event_metadata, metadata.types())
124 }
125
126 pub fn as_event<E: StaticEvent>(&self) -> Result<Option<E>, Error> {
131 if self.pallet_name() == E::PALLET && self.variant_name() == E::EVENT {
132 Ok(Some(E::decode(&mut self.field_bytes())?))
133 } else {
134 Ok(None)
135 }
136 }
137
138 pub fn as_root_event<E: RootEvent>(&self, metadata: &Metadata) -> Result<E, Error> {
142 let event_metadata = self.event_metadata(metadata)?;
143 self.as_root_event_inner(metadata, &event_metadata)
144 }
145
146 pub fn topics(&self) -> &[Hash] {
148 &self.topics
149 }
150
151 pub fn pallet_bytes(&self) -> &[u8] {
152 &self.pallet_bytes
153 }
154}
155
156impl<Hash: Encode + Decode> RawEventDetails<Hash> {
157 pub fn has_failed(&self) -> bool {
159 self.pallet_name() == "System" && self.variant_name() == "ExtrinsicFailed"
160 }
161
162 pub fn get_associated_dispatch_error(&self, metadata: &Metadata) -> Option<DispatchError> {
164 match self.has_failed() {
165 true => Some(
166 DispatchError::decode_from(self.field_bytes(), metadata)
167 .unwrap_or(DispatchError::CannotLookup),
168 ),
169 false => None,
170 }
171 }
172
173 pub fn is_code_update(&self) -> bool {
175 self.pallet_name() == "System" && self.variant_name() == "CodeUpdated"
176 }
177}
178
179impl<Hash: Encode + Decode> From<EventDetails<Hash>> for RawEventDetails<Hash> {
180 fn from(val: EventDetails<Hash>) -> Self {
181 val.to_raw()
182 }
183}
184
185impl<Hash: Encode + Decode> RawEventDetails<Hash> {
187 pub(crate) fn decode_from(
189 metadata: &Metadata,
190 all_bytes: Arc<[u8]>,
191 start_idx: usize,
192 index: u32,
193 ) -> Result<Self, Error> {
194 let input = &mut &all_bytes[start_idx..];
195
196 let phase = Phase::decode(input)?;
197
198 let event_start_idx = all_bytes.len() - input.len();
199
200 let pallet_index = u8::decode(input)?;
201 let variant_index = u8::decode(input)?;
202
203 let event_fields_start_idx = all_bytes.len() - input.len();
204
205 let event_pallet = metadata.pallet_by_index_err(pallet_index)?;
207 let event_variant = event_pallet
208 .event_variant_by_index(variant_index)
209 .ok_or(MetadataError::VariantIndexNotFound(variant_index))?;
210 let pallet_name = event_pallet.name().to_string();
211 let variant_name = event_variant.name.to_string();
212 debug!("Decoding Event '{}::{}'", &pallet_name, &variant_name);
213
214 for field_metadata in &event_variant.fields {
216 scale_decode::visitor::decode_with_visitor(
218 input,
219 field_metadata.ty.id,
220 metadata.types(),
221 scale_decode::visitor::IgnoreVisitor::new(),
222 )
223 .map_err(scale_decode::Error::from)?;
224 }
225
226 let event_fields_end_idx = all_bytes.len() - input.len();
228
229 let topics = Vec::<Hash>::decode(input)?;
231
232 let end_idx = all_bytes.len() - input.len();
234 let pallet_bytes: Vec<u8> = all_bytes[event_start_idx + 1..event_fields_end_idx].into();
235 let pallet_index = all_bytes[event_fields_start_idx - 2];
236 let variant_index = all_bytes[event_fields_start_idx - 1];
237 let bytes: Vec<u8> = all_bytes[start_idx..end_idx].into();
238 let field_bytes: Vec<u8> = all_bytes[event_fields_start_idx..event_fields_end_idx].into();
239
240 Ok(RawEventDetails {
241 phase,
242 index,
243 bytes,
244 field_bytes,
245 pallet_index,
246 pallet_name,
247 pallet_bytes,
248 variant_index,
249 variant_name,
250 topics,
251 })
252 }
253
254 pub(crate) fn event_metadata_unchecked<'a>(
256 &'a self,
257 metadata: &'a Metadata,
258 ) -> EventMetadataDetails<'a> {
259 let pallet = metadata
260 .pallet_by_index(self.pallet_index())
261 .expect("event pallet to be found; we did this already during decoding");
262 let variant = pallet
263 .event_variant_by_index(self.variant_index())
264 .expect("event variant to be found; we did this already during decoding");
265
266 EventMetadataDetails { pallet, variant }
267 }
268
269 pub(crate) fn field_values_unchecked(
272 &self,
273 metadata: &Metadata,
274 ) -> Result<Composite<u32>, Error> {
275 let event_metadata = self.event_metadata_unchecked(metadata);
276 self.field_values_inner(&event_metadata, metadata.types())
277 }
278
279 pub(crate) fn as_root_event_unchecked<E: RootEvent>(
283 &self,
284 metadata: &Metadata,
285 ) -> Result<E, Error> {
286 let event_metadata = self.event_metadata_unchecked(metadata);
287 self.as_root_event_inner(metadata, &event_metadata)
288 }
289
290 pub(crate) fn as_root_event_inner<E: RootEvent>(
291 &self,
292 metadata: &Metadata,
293 event_metadata: &EventMetadataDetails,
294 ) -> Result<E, Error> {
295 let pallet_bytes = self.pallet_bytes();
296 let pallet_event_ty = event_metadata.pallet.event_ty_id().ok_or_else(|| {
297 MetadataError::EventTypeNotFoundInPallet(event_metadata.pallet.index())
298 })?;
299
300 E::root_event(pallet_bytes, self.pallet_name(), pallet_event_ty, metadata)
301 }
302
303 fn metadata_sanity_check(&self, event_metadata: &EventMetadataDetails) -> Result<(), Error> {
304 if event_metadata.pallet.name() != self.pallet_name()
305 || event_metadata.variant.name != self.variant_name()
306 {
307 return Err(Error::Metadata(MetadataError::MetadataMismatch))
308 }
309 Ok(())
310 }
311
312 fn field_values_inner(
313 &self,
314 event_metadata: &EventMetadataDetails,
315 types: &PortableRegistry,
316 ) -> Result<Composite<u32>, Error> {
317 let bytes = &mut self.field_bytes();
318 let mut fields = event_metadata
319 .variant
320 .fields
321 .iter()
322 .map(|f| scale_decode::Field::new(f.ty.id, f.name.as_deref()));
323 let decoded = scale_value::scale::decode_as_fields(bytes, &mut fields, types)?;
324
325 Ok(decoded)
326 }
327}
328
329#[cfg(test)]
331pub(crate) mod test_utils {
332 use super::*;
333 use crate::{events::Compact, Events};
334 use codec::Encode;
335 use frame_metadata::{
336 v15::{
337 CustomMetadata, ExtrinsicMetadata, OuterEnums, PalletEventMetadata, PalletMetadata,
338 RuntimeMetadataV15,
339 },
340 RuntimeMetadataPrefixed,
341 };
342 use scale_info::{meta_type, TypeInfo};
343 use sp_core::H256;
344
345 #[derive(
347 Encode,
348 Decode,
349 TypeInfo,
350 Clone,
351 Debug,
352 PartialEq,
353 Eq,
354 scale_encode::EncodeAsType,
355 scale_decode::DecodeAsType,
356 )]
357 pub enum AllEvents<Ev> {
358 Test(Ev),
359 }
360
361 #[derive(Encode)]
364 pub struct EventRecord<E: Encode> {
365 phase: Phase,
366 event: AllEvents<E>,
367 topics: Vec<H256>,
368 }
369
370 impl<E: Encode> EventRecord<E> {
371 pub fn new(phase: Phase, event: E, topics: Vec<H256>) -> Self {
373 Self { phase, event: AllEvents::Test(event), topics }
374 }
375 }
376
377 pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
380 EventRecord::new(phase, event, vec![])
381 }
382
383 pub fn metadata<E: TypeInfo + 'static>() -> Metadata {
386 #[allow(unused)]
391 #[derive(TypeInfo)]
392 struct ExtrinsicType<Call> {
393 call: Call,
394 }
395 #[allow(unused)]
398 #[derive(TypeInfo)]
399 enum RuntimeCall {
400 PalletName(Pallet),
401 }
402 #[allow(unused)]
404 #[derive(TypeInfo)]
405 enum Pallet {
406 #[allow(unused)]
407 SomeCall,
408 }
409
410 let pallets = vec![PalletMetadata {
411 name: "Test",
412 storage: None,
413 calls: None,
414 event: Some(PalletEventMetadata { ty: meta_type::<E>() }),
415 constants: vec![],
416 error: None,
417 index: 0,
418 docs: vec![],
419 }];
420
421 let extrinsic = ExtrinsicMetadata {
422 version: 0,
423 signed_extensions: vec![],
424 address_ty: meta_type::<()>(),
425 call_ty: meta_type::<RuntimeCall>(),
426 signature_ty: meta_type::<()>(),
427 extra_ty: meta_type::<()>(),
428 };
429
430 let meta = RuntimeMetadataV15::new(
431 pallets,
432 extrinsic,
433 meta_type::<()>(),
434 vec![],
435 OuterEnums {
436 call_enum_ty: meta_type::<()>(),
437 event_enum_ty: meta_type::<AllEvents<E>>(),
438 error_enum_ty: meta_type::<()>(),
439 },
440 CustomMetadata { map: Default::default() },
441 );
442 let runtime_metadata: RuntimeMetadataPrefixed = meta.into();
443 Metadata::try_from(runtime_metadata).unwrap()
444 }
445
446 pub fn events<E: Decode + Encode>(
449 metadata: Metadata,
450 event_records: Vec<EventRecord<E>>,
451 ) -> Events<H256> {
452 let num_events = event_records.len() as u32;
453 let mut event_bytes = Vec::new();
454 for ev in event_records {
455 ev.encode_to(&mut event_bytes);
456 }
457 events_raw(metadata, event_bytes, num_events)
458 }
459
460 pub fn events_raw(metadata: Metadata, event_bytes: Vec<u8>, num_events: u32) -> Events<H256> {
463 let mut all_event_bytes = Compact(num_events).encode();
465 all_event_bytes.extend(event_bytes);
466 Events::new(metadata, H256::default(), all_event_bytes)
467 }
468}
469
470#[cfg(test)]
471mod tests {
472 use super::{
473 test_utils::{event_record, events, events_raw, EventRecord},
474 *,
475 };
476 use codec::Encode;
477 use scale_info::TypeInfo;
478 use scale_value::Value;
479 use sp_core::H256;
480
481 fn metadata<E: TypeInfo + 'static>() -> Metadata {
483 test_utils::metadata::<E>()
484 }
485
486 #[derive(Debug, PartialEq, Eq, Clone)]
490 pub struct TestRawEventDetails {
491 pub phase: Phase,
492 pub index: u32,
493 pub pallet: String,
494 pub pallet_index: u8,
495 pub variant: String,
496 pub variant_index: u8,
497 pub fields: Vec<scale_value::Value>,
498 }
499
500 pub fn assert_raw_events_match(
503 actual: RawEventDetails<H256>,
504 expected: TestRawEventDetails,
505 metadata: &Metadata,
506 ) {
507 let actual_fields_no_context: Vec<_> = actual
508 .field_values(metadata)
509 .expect("can decode field values (2)")
510 .into_values()
511 .map(|value| value.remove_context())
512 .collect();
513
514 assert_eq!(actual.phase(), expected.phase);
516 assert_eq!(actual.index(), expected.index);
517 assert_eq!(actual.pallet_name(), expected.pallet);
518 assert_eq!(actual.pallet_index(), expected.pallet_index);
519 assert_eq!(actual.variant_name(), expected.variant);
520 assert_eq!(actual.variant_index(), expected.variant_index);
521 assert_eq!(actual_fields_no_context, expected.fields);
522 }
523
524 #[test]
525 fn dynamically_decode_single_event() {
526 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
527 enum Event {
528 A(u8, bool, Vec<String>),
529 }
530
531 let metadata = metadata::<Event>();
533
534 let event = Event::A(1, true, vec!["Hi".into()]);
537 let events = events::<Event>(
538 metadata.clone(),
539 vec![event_record(Phase::ApplyExtrinsic(123), event)],
540 );
541
542 let mut event_details_iter = events.iter();
543 assert_raw_events_match(
544 event_details_iter.next().unwrap().unwrap().to_raw(),
545 TestRawEventDetails {
546 phase: Phase::ApplyExtrinsic(123),
547 index: 0,
548 pallet: "Test".to_string(),
549 pallet_index: 0,
550 variant: "A".to_string(),
551 variant_index: 0,
552 fields: vec![
553 Value::u128(1),
554 Value::bool(true),
555 Value::unnamed_composite(vec![Value::string("Hi")]),
556 ],
557 },
558 &metadata,
559 );
560 assert!(event_details_iter.next().is_none());
561 }
562
563 #[test]
564 fn dynamically_decode_multiple_events() {
565 #[derive(Clone, Copy, Debug, PartialEq, Decode, Encode, TypeInfo)]
566 enum Event {
567 A(u8),
568 B(bool),
569 }
570
571 let metadata = metadata::<Event>();
573
574 let event1 = Event::A(1);
577 let event2 = Event::B(true);
578 let event3 = Event::A(234);
579
580 let events = events::<Event>(
581 metadata.clone(),
582 vec![
583 event_record(Phase::Initialization, event1),
584 event_record(Phase::ApplyExtrinsic(123), event2),
585 event_record(Phase::Finalization, event3),
586 ],
587 );
588
589 let mut event_details_iter = events.iter();
590
591 assert_raw_events_match(
592 event_details_iter.next().unwrap().unwrap().to_raw(),
593 TestRawEventDetails {
594 index: 0,
595 phase: Phase::Initialization,
596 pallet: "Test".to_string(),
597 pallet_index: 0,
598 variant: "A".to_string(),
599 variant_index: 0,
600 fields: vec![Value::u128(1)],
601 },
602 &metadata,
603 );
604 assert_raw_events_match(
605 event_details_iter.next().unwrap().unwrap().to_raw(),
606 TestRawEventDetails {
607 index: 1,
608 phase: Phase::ApplyExtrinsic(123),
609 pallet: "Test".to_string(),
610 pallet_index: 0,
611 variant: "B".to_string(),
612 variant_index: 1,
613 fields: vec![Value::bool(true)],
614 },
615 &metadata,
616 );
617 assert_raw_events_match(
618 event_details_iter.next().unwrap().unwrap().to_raw(),
619 TestRawEventDetails {
620 index: 2,
621 phase: Phase::Finalization,
622 pallet: "Test".to_string(),
623 pallet_index: 0,
624 variant: "A".to_string(),
625 variant_index: 0,
626 fields: vec![Value::u128(234)],
627 },
628 &metadata,
629 );
630 assert!(event_details_iter.next().is_none());
631 }
632
633 #[test]
634 fn dynamically_decode_multiple_events_until_error() {
635 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
636 enum Event {
637 A(u8),
638 B(bool),
639 }
640
641 let metadata = metadata::<Event>();
643
644 let mut event_bytes = vec![];
646 event_record(Phase::Initialization, Event::A(1)).encode_to(&mut event_bytes);
647 event_record(Phase::ApplyExtrinsic(123), Event::B(true)).encode_to(&mut event_bytes);
648
649 event_bytes.extend_from_slice(&[3, 127, 45, 0, 2]);
651
652 let events = events_raw(
655 metadata.clone(),
656 event_bytes,
657 3, );
659 let mut event_details_iter = events.iter();
660 assert_raw_events_match(
661 event_details_iter.next().unwrap().unwrap().to_raw(),
662 TestRawEventDetails {
663 index: 0,
664 phase: Phase::Initialization,
665 pallet: "Test".to_string(),
666 pallet_index: 0,
667 variant: "A".to_string(),
668 variant_index: 0,
669 fields: vec![Value::u128(1)],
670 },
671 &metadata,
672 );
673 assert_raw_events_match(
674 event_details_iter.next().unwrap().unwrap().to_raw(),
675 TestRawEventDetails {
676 index: 1,
677 phase: Phase::ApplyExtrinsic(123),
678 pallet: "Test".to_string(),
679 pallet_index: 0,
680 variant: "B".to_string(),
681 variant_index: 1,
682 fields: vec![Value::bool(true)],
683 },
684 &metadata,
685 );
686
687 assert!(event_details_iter.next().unwrap().is_err());
689 assert!(event_details_iter.next().is_none());
691 assert!(event_details_iter.next().is_none());
692 }
693
694 #[test]
695 fn compact_event_field() {
696 #[derive(Clone, Debug, PartialEq, Encode, Decode, TypeInfo)]
697 enum Event {
698 A(#[codec(compact)] u32),
699 }
700
701 let metadata = metadata::<Event>();
703
704 let events =
707 events::<Event>(metadata.clone(), vec![event_record(Phase::Finalization, Event::A(1))]);
708
709 let mut event_details_iter = events.iter();
711 assert_raw_events_match(
712 event_details_iter.next().unwrap().unwrap().to_raw(),
713 TestRawEventDetails {
714 index: 0,
715 phase: Phase::Finalization,
716 pallet: "Test".to_string(),
717 pallet_index: 0,
718 variant: "A".to_string(),
719 variant_index: 0,
720 fields: vec![Value::u128(1)],
721 },
722 &metadata,
723 );
724 assert!(event_details_iter.next().is_none());
725 }
726
727 #[test]
728 fn compact_wrapper_struct_field() {
729 #[derive(Clone, Decode, Debug, PartialEq, Encode, TypeInfo)]
730 enum Event {
731 A(#[codec(compact)] CompactWrapper),
732 }
733
734 #[derive(Clone, Decode, Debug, PartialEq, codec::CompactAs, Encode, TypeInfo)]
735 struct CompactWrapper(u64);
736
737 let metadata = metadata::<Event>();
739
740 let events = events::<Event>(
743 metadata.clone(),
744 vec![event_record(Phase::Finalization, Event::A(CompactWrapper(1)))],
745 );
746
747 let mut event_details_iter = events.iter();
749 assert_raw_events_match(
750 event_details_iter.next().unwrap().unwrap().to_raw(),
751 TestRawEventDetails {
752 index: 0,
753 phase: Phase::Finalization,
754 pallet: "Test".to_string(),
755 pallet_index: 0,
756 variant: "A".to_string(),
757 variant_index: 0,
758 fields: vec![Value::unnamed_composite(vec![Value::u128(1)])],
759 },
760 &metadata,
761 );
762 assert!(event_details_iter.next().is_none());
763 }
764
765 #[test]
766 fn event_containing_explicit_index() {
767 #[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
768 #[repr(u8)]
769 #[allow(trivial_numeric_casts, clippy::unnecessary_cast)] pub enum MyType {
771 B = 10u8,
772 }
773
774 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
775 enum Event {
776 A(MyType),
777 }
778
779 let metadata = metadata::<Event>();
781
782 let events = events::<Event>(
785 metadata.clone(),
786 vec![event_record(Phase::Finalization, Event::A(MyType::B))],
787 );
788
789 let mut event_details_iter = events.iter();
791 assert_raw_events_match(
792 event_details_iter.next().unwrap().unwrap().to_raw(),
793 TestRawEventDetails {
794 index: 0,
795 phase: Phase::Finalization,
796 pallet: "Test".to_string(),
797 pallet_index: 0,
798 variant: "A".to_string(),
799 variant_index: 0,
800 fields: vec![Value::unnamed_variant("B", vec![])],
801 },
802 &metadata,
803 );
804 assert!(event_details_iter.next().is_none());
805 }
806
807 #[test]
808 fn topics() {
809 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo, scale_decode::DecodeAsType)]
810 enum Event {
811 A(u8, bool, Vec<String>),
812 }
813
814 let metadata = metadata::<Event>();
816
817 let event = Event::A(1, true, vec!["Hi".into()]);
820 let topics = vec![H256::from_low_u64_le(123), H256::from_low_u64_le(456)];
821 let events = events::<Event>(
822 metadata,
823 vec![EventRecord::new(Phase::ApplyExtrinsic(123), event, topics.clone())],
824 );
825
826 let ev = events
827 .iter()
828 .next()
829 .expect("one event expected")
830 .expect("event should be extracted OK");
831
832 assert_eq!(topics, ev.topics());
833 }
834
835 #[test]
836 fn encode_decode() {
837 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo, scale_decode::DecodeAsType)]
838 enum Event {
839 A(#[codec(compact)] u32),
840 }
841
842 let metadata = metadata::<Event>();
844
845 let events =
848 events::<Event>(metadata.clone(), vec![event_record(Phase::Finalization, Event::A(1))]);
849
850 let raw_event_details = events.iter().next().unwrap().unwrap().to_raw();
852
853 let encoded = raw_event_details.encode();
855 let decoded = RawEventDetails::decode(&mut encoded.as_slice()).unwrap();
856
857 assert_eq!(raw_event_details, decoded);
858 }
859}