1use crate::{error::Error, metadata::PalletMetadata, Metadata, StaticEvent};
13use alloc::{sync::Arc, vec::Vec};
14use codec::{Compact, Decode, Encode};
15
16mod event_details;
17mod raw_event_details;
18pub use event_details::EventDetails;
19pub use raw_event_details::RawEventDetails;
20
21#[derive(Clone)]
24pub struct Events<Hash> {
25 metadata: Metadata,
26 block_hash: Hash,
27 event_bytes: Arc<[u8]>,
31 start_idx: usize,
32 num_events: u32,
33}
34
35impl<Hash: core::fmt::Debug> core::fmt::Debug for Events<Hash> {
37 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38 f.debug_struct("Events")
39 .field("block_hash", &self.block_hash)
40 .field("event_bytes", &self.event_bytes)
41 .field("start_idx", &self.start_idx)
42 .field("num_events", &self.num_events)
43 .finish()
44 }
45}
46
47impl<Hash: Copy + Encode + Decode> Events<Hash> {
48 pub fn new(metadata: Metadata, block_hash: Hash, event_bytes: Vec<u8>) -> Self {
49 let cursor = &mut &*event_bytes;
56 let num_events = <Compact<u32>>::decode(cursor).unwrap_or(Compact(0)).0;
57
58 let start_idx = event_bytes.len() - cursor.len();
60
61 Self { metadata, block_hash, event_bytes: event_bytes.into(), start_idx, num_events }
62 }
63
64 pub fn len(&self) -> u32 {
66 self.num_events
67 }
68
69 pub fn is_empty(&self) -> bool {
72 self.num_events == 0
73 }
74
75 pub fn block_hash(&self) -> Hash {
77 self.block_hash
78 }
79
80 pub fn event_bytes(&self) -> Arc<[u8]> {
82 self.event_bytes.clone()
83 }
84
85 pub fn iter(
91 &self,
92 ) -> impl Iterator<Item = Result<EventDetails<Hash>, Error>> + Send + Sync + 'static {
93 let event_bytes = self.event_bytes.clone();
95 let metadata = self.metadata.clone();
96 let num_events = self.num_events;
97
98 let mut pos = self.start_idx;
99 let mut index = 0;
100 core::iter::from_fn(move || {
101 if event_bytes.len() <= pos || num_events == index {
102 None
103 } else {
104 match EventDetails::decode_from(metadata.clone(), event_bytes.clone(), pos, index) {
105 Ok(event_details) => {
106 pos += event_details.bytes().len();
108 index += 1;
110 Some(Ok(event_details))
112 },
113 Err(e) => {
114 pos = event_bytes.len();
118 Some(Err(e))
119 },
120 }
121 }
122 })
123 }
124
125 pub fn find<Ev: StaticEvent>(&self) -> impl Iterator<Item = Result<Ev, Error>> + '_ {
129 self.iter().filter_map(|ev| ev.and_then(|ev| ev.as_event::<Ev>()).transpose())
130 }
131
132 pub fn find_first<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
135 self.find::<Ev>().next().transpose()
136 }
137
138 pub fn find_last<Ev: StaticEvent>(&self) -> Result<Option<Ev>, Error> {
141 self.find::<Ev>().last().transpose()
142 }
143
144 pub fn has<Ev: StaticEvent>(&self) -> Result<bool, Error> {
146 Ok(self.find::<Ev>().next().transpose()?.is_some())
147 }
148}
149
150#[doc(hidden)]
157pub trait RootEvent: Sized {
158 fn root_event(
161 pallet_bytes: &[u8],
162 pallet_name: &str,
163 pallet_event_ty: u32,
164 metadata: &Metadata,
165 ) -> Result<Self, Error>;
166}
167
168#[derive(Clone)]
171pub struct EventMetadataDetails<'a> {
172 pub pallet: PalletMetadata<'a>,
173 pub variant: &'a scale_info::Variant<scale_info::form::PortableForm>,
174}
175
176#[cfg(test)]
177mod tests {
178 use super::*;
179 use crate::{
180 test_utils::{
181 event_record, events, events_raw, metadata_with_version, SupportedMetadataVersions,
182 },
183 Phase,
184 };
185 use codec::Encode;
186 use scale_info::TypeInfo;
187 use scale_value::Value;
188 use sp_core::H256;
189 use test_case::test_case;
190
191 #[derive(Debug, PartialEq, Clone)]
195 pub struct TestRawEventDetails {
196 pub phase: Phase,
197 pub index: u32,
198 pub pallet: String,
199 pub pallet_index: u8,
200 pub variant: String,
201 pub variant_index: u8,
202 pub fields: Vec<Value>,
203 }
204
205 pub fn assert_raw_events_match(actual: EventDetails<H256>, expected: TestRawEventDetails) {
208 let actual_fields_no_context: Vec<_> = actual
209 .field_values()
210 .expect("can decode field values (2)")
211 .into_values()
212 .map(|value| value.remove_context())
213 .collect();
214
215 assert_eq!(actual.phase(), expected.phase);
217 assert_eq!(actual.index(), expected.index);
218 assert_eq!(actual.pallet_name(), expected.pallet);
219 assert_eq!(actual.pallet_index(), expected.pallet_index);
220 assert_eq!(actual.variant_name(), expected.variant);
221 assert_eq!(actual.variant_index(), expected.variant_index);
222 assert_eq!(actual_fields_no_context, expected.fields);
223 }
224
225 #[test_case(SupportedMetadataVersions::V14)]
226 #[test_case(SupportedMetadataVersions::V15)]
227 fn dynamically_decode_single_event(metadata_version: SupportedMetadataVersions) {
228 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
229 enum Event {
230 A(u8, bool, Vec<String>),
231 }
232
233 let metadata = metadata_with_version::<Event>(metadata_version);
235
236 let event = Event::A(1, true, vec!["Hi".into()]);
239 let events = events::<Event>(
240 metadata.clone(),
241 vec![event_record(Phase::ApplyExtrinsic(123), event)],
242 );
243
244 let mut event_details = events.iter();
245 assert_raw_events_match(
246 event_details.next().unwrap().unwrap(),
247 TestRawEventDetails {
248 phase: Phase::ApplyExtrinsic(123),
249 index: 0,
250 pallet: "Test".to_string(),
251 pallet_index: 0,
252 variant: "A".to_string(),
253 variant_index: 0,
254 fields: vec![
255 Value::u128(1u128),
256 Value::bool(true),
257 Value::unnamed_composite(vec![Value::string("Hi")]),
258 ],
259 },
260 );
261 assert!(event_details.next().is_none());
262 }
263
264 #[test_case(SupportedMetadataVersions::V14)]
265 #[test_case(SupportedMetadataVersions::V15)]
266 fn dynamically_decode_multiple_events(metadata_version: SupportedMetadataVersions) {
267 #[derive(Clone, Copy, Debug, PartialEq, Decode, Encode, TypeInfo)]
268 enum Event {
269 A(u8),
270 B(bool),
271 }
272
273 let metadata = metadata_with_version::<Event>(metadata_version);
275
276 let event1 = Event::A(1);
279 let event2 = Event::B(true);
280 let event3 = Event::A(234);
281
282 let events = events::<Event>(
283 metadata.clone(),
284 vec![
285 event_record(Phase::Initialization, event1),
286 event_record(Phase::ApplyExtrinsic(123), event2),
287 event_record(Phase::Finalization, event3),
288 ],
289 );
290
291 let mut event_details = events.iter();
292
293 assert_raw_events_match(
294 event_details.next().unwrap().unwrap(),
295 TestRawEventDetails {
296 index: 0,
297 phase: Phase::Initialization,
298 pallet: "Test".to_string(),
299 pallet_index: 0,
300 variant: "A".to_string(),
301 variant_index: 0,
302 fields: vec![Value::u128(1u128)],
303 },
304 );
305 assert_raw_events_match(
306 event_details.next().unwrap().unwrap(),
307 TestRawEventDetails {
308 index: 1,
309 phase: Phase::ApplyExtrinsic(123),
310 pallet: "Test".to_string(),
311 pallet_index: 0,
312 variant: "B".to_string(),
313 variant_index: 1,
314 fields: vec![Value::bool(true)],
315 },
316 );
317 assert_raw_events_match(
318 event_details.next().unwrap().unwrap(),
319 TestRawEventDetails {
320 index: 2,
321 phase: Phase::Finalization,
322 pallet: "Test".to_string(),
323 pallet_index: 0,
324 variant: "A".to_string(),
325 variant_index: 0,
326 fields: vec![Value::u128(234u128)],
327 },
328 );
329 assert!(event_details.next().is_none());
330 }
331
332 #[test_case(SupportedMetadataVersions::V14)]
333 #[test_case(SupportedMetadataVersions::V15)]
334 fn dynamically_decode_multiple_events_until_error(metadata_version: SupportedMetadataVersions) {
335 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
336 enum Event {
337 A(u8),
338 B(bool),
339 }
340
341 let metadata = metadata_with_version::<Event>(metadata_version);
343
344 let mut event_bytes = vec![];
346 event_record(Phase::Initialization, Event::A(1)).encode_to(&mut event_bytes);
347 event_record(Phase::ApplyExtrinsic(123), Event::B(true)).encode_to(&mut event_bytes);
348
349 event_bytes.extend_from_slice(&[3, 127, 45, 0, 2]);
351
352 let events = events_raw(
355 metadata.clone(),
356 event_bytes,
357 3, );
359
360 let mut events_iter = events.iter();
361 assert_raw_events_match(
362 events_iter.next().unwrap().unwrap(),
363 TestRawEventDetails {
364 index: 0,
365 phase: Phase::Initialization,
366 pallet: "Test".to_string(),
367 pallet_index: 0,
368 variant: "A".to_string(),
369 variant_index: 0,
370 fields: vec![Value::u128(1u128)],
371 },
372 );
373 assert_raw_events_match(
374 events_iter.next().unwrap().unwrap(),
375 TestRawEventDetails {
376 index: 1,
377 phase: Phase::ApplyExtrinsic(123),
378 pallet: "Test".to_string(),
379 pallet_index: 0,
380 variant: "B".to_string(),
381 variant_index: 1,
382 fields: vec![Value::bool(true)],
383 },
384 );
385
386 assert!(events_iter.next().unwrap().is_err());
388 assert!(events_iter.next().is_none());
390 assert!(events_iter.next().is_none());
391 }
392
393 #[test_case(SupportedMetadataVersions::V14)]
394 #[test_case(SupportedMetadataVersions::V15)]
395 fn compact_event_field(metadata_version: SupportedMetadataVersions) {
396 #[derive(Clone, Debug, PartialEq, Encode, Decode, TypeInfo)]
397 enum Event {
398 A(#[codec(compact)] u32),
399 }
400
401 let metadata = metadata_with_version::<Event>(metadata_version);
403
404 let events =
407 events::<Event>(metadata.clone(), vec![event_record(Phase::Finalization, Event::A(1))]);
408
409 let mut event_details = events.iter();
411 assert_raw_events_match(
412 event_details.next().unwrap().unwrap(),
413 TestRawEventDetails {
414 index: 0,
415 phase: Phase::Finalization,
416 pallet: "Test".to_string(),
417 pallet_index: 0,
418 variant: "A".to_string(),
419 variant_index: 0,
420 fields: vec![Value::u128(1u128)],
421 },
422 );
423 assert!(event_details.next().is_none());
424 }
425
426 #[test_case(SupportedMetadataVersions::V14)]
427 #[test_case(SupportedMetadataVersions::V15)]
428 fn compact_wrapper_struct_field(metadata_version: SupportedMetadataVersions) {
429 #[derive(Clone, Decode, Debug, PartialEq, Encode, TypeInfo)]
430 enum Event {
431 A(#[codec(compact)] CompactWrapper),
432 }
433
434 #[derive(Clone, Decode, Debug, PartialEq, codec::CompactAs, Encode, TypeInfo)]
435 struct CompactWrapper(u64);
436
437 let metadata = metadata_with_version::<Event>(metadata_version);
439
440 let events = events::<Event>(
443 metadata.clone(),
444 vec![event_record(Phase::Finalization, Event::A(CompactWrapper(1)))],
445 );
446
447 let mut event_details = events.iter();
449 assert_raw_events_match(
450 event_details.next().unwrap().unwrap(),
451 TestRawEventDetails {
452 index: 0,
453 phase: Phase::Finalization,
454 pallet: "Test".to_string(),
455 pallet_index: 0,
456 variant: "A".to_string(),
457 variant_index: 0,
458 fields: vec![Value::unnamed_composite(vec![Value::u128(1)])],
459 },
460 );
461 assert!(event_details.next().is_none());
462 }
463
464 #[test_case(SupportedMetadataVersions::V14)]
465 #[test_case(SupportedMetadataVersions::V15)]
466 fn event_containing_explicit_index(metadata_version: SupportedMetadataVersions) {
467 #[derive(Clone, Debug, PartialEq, Eq, Decode, Encode, TypeInfo)]
468 #[repr(u8)]
469 #[allow(trivial_numeric_casts, clippy::unnecessary_cast)] pub enum MyType {
471 B = 10u8,
472 }
473
474 #[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo)]
475 enum Event {
476 A(MyType),
477 }
478
479 let metadata = metadata_with_version::<Event>(metadata_version);
481
482 let events = events::<Event>(
485 metadata.clone(),
486 vec![event_record(Phase::Finalization, Event::A(MyType::B))],
487 );
488
489 let mut event_details = events.iter();
491 assert_raw_events_match(
492 event_details.next().unwrap().unwrap(),
493 TestRawEventDetails {
494 index: 0,
495 phase: Phase::Finalization,
496 pallet: "Test".to_string(),
497 pallet_index: 0,
498 variant: "A".to_string(),
499 variant_index: 0,
500 fields: vec![Value::unnamed_variant("B", vec![])],
501 },
502 );
503 assert!(event_details.next().is_none());
504 }
505}