mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-14 06:21:11 +00:00
Add topics to EventDetails (#989)
* Add topics to `EventDetails` * Update comment * Fmt * Clippy
This commit is contained in:
@@ -560,7 +560,7 @@ impl<T: Config> ExtrinsicEvents<T> {
|
|||||||
///
|
///
|
||||||
/// This works in the same way that [`events::Events::iter()`] does, with the
|
/// This works in the same way that [`events::Events::iter()`] does, with the
|
||||||
/// exception that it filters out events not related to the submitted extrinsic.
|
/// exception that it filters out events not related to the submitted extrinsic.
|
||||||
pub fn iter(&self) -> impl Iterator<Item = Result<events::EventDetails, Error>> + '_ {
|
pub fn iter(&self) -> impl Iterator<Item = Result<events::EventDetails<T>, Error>> + '_ {
|
||||||
self.events.iter().filter(|ev| {
|
self.events.iter().filter(|ev| {
|
||||||
ev.as_ref()
|
ev.as_ref()
|
||||||
.map(|ev| ev.phase() == events::Phase::ApplyExtrinsic(self.idx))
|
.map(|ev| ev.phase() == events::Phase::ApplyExtrinsic(self.idx))
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ impl<T: Config> Events<T> {
|
|||||||
// use of it with our `FilterEvents` stuff.
|
// use of it with our `FilterEvents` stuff.
|
||||||
pub fn iter(
|
pub fn iter(
|
||||||
&self,
|
&self,
|
||||||
) -> impl Iterator<Item = Result<EventDetails, Error>> + Send + Sync + 'static {
|
) -> impl Iterator<Item = Result<EventDetails<T>, Error>> + Send + Sync + 'static {
|
||||||
// The event bytes ignoring the compact encoded length on the front:
|
// The event bytes ignoring the compact encoded length on the front:
|
||||||
let event_bytes = self.event_bytes.clone();
|
let event_bytes = self.event_bytes.clone();
|
||||||
let metadata = self.metadata.clone();
|
let metadata = self.metadata.clone();
|
||||||
@@ -133,12 +133,7 @@ impl<T: Config> Events<T> {
|
|||||||
if event_bytes.len() <= pos || num_events == index {
|
if event_bytes.len() <= pos || num_events == index {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
match EventDetails::decode_from::<T>(
|
match EventDetails::decode_from(metadata.clone(), event_bytes.clone(), pos, index) {
|
||||||
metadata.clone(),
|
|
||||||
event_bytes.clone(),
|
|
||||||
pos,
|
|
||||||
index,
|
|
||||||
) {
|
|
||||||
Ok(event_details) => {
|
Ok(event_details) => {
|
||||||
// Skip over decoded bytes in next iteration:
|
// Skip over decoded bytes in next iteration:
|
||||||
pos += event_details.bytes().len();
|
pos += event_details.bytes().len();
|
||||||
@@ -189,7 +184,7 @@ impl<T: Config> Events<T> {
|
|||||||
|
|
||||||
/// The event details.
|
/// The event details.
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct EventDetails {
|
pub struct EventDetails<T: Config> {
|
||||||
phase: Phase,
|
phase: Phase,
|
||||||
/// The index of the event in the list of events in a given block.
|
/// The index of the event in the list of events in a given block.
|
||||||
index: u32,
|
index: u32,
|
||||||
@@ -205,16 +200,17 @@ pub struct EventDetails {
|
|||||||
// end of everything (fields + topics)
|
// end of everything (fields + topics)
|
||||||
end_idx: usize,
|
end_idx: usize,
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
|
topics: Vec<T::Hash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventDetails {
|
impl<T: Config> EventDetails<T> {
|
||||||
// Attempt to dynamically decode a single event from our events input.
|
// Attempt to dynamically decode a single event from our events input.
|
||||||
fn decode_from<T: Config>(
|
fn decode_from(
|
||||||
metadata: Metadata,
|
metadata: Metadata,
|
||||||
all_bytes: Arc<[u8]>,
|
all_bytes: Arc<[u8]>,
|
||||||
start_idx: usize,
|
start_idx: usize,
|
||||||
index: u32,
|
index: u32,
|
||||||
) -> Result<EventDetails, Error> {
|
) -> Result<EventDetails<T>, Error> {
|
||||||
let input = &mut &all_bytes[start_idx..];
|
let input = &mut &all_bytes[start_idx..];
|
||||||
|
|
||||||
let phase = Phase::decode(input)?;
|
let phase = Phase::decode(input)?;
|
||||||
@@ -252,9 +248,8 @@ impl EventDetails {
|
|||||||
// the end of the field bytes.
|
// the end of the field bytes.
|
||||||
let event_fields_end_idx = all_bytes.len() - input.len();
|
let event_fields_end_idx = all_bytes.len() - input.len();
|
||||||
|
|
||||||
// topics come after the event data in EventRecord. They aren't used for
|
// topics come after the event data in EventRecord.
|
||||||
// anything at the moment, so just decode and throw them away.
|
let topics = Vec::<T::Hash>::decode(input)?;
|
||||||
let _topics = Vec::<T::Hash>::decode(input)?;
|
|
||||||
|
|
||||||
// what bytes did we skip over in total, including topics.
|
// what bytes did we skip over in total, including topics.
|
||||||
let end_idx = all_bytes.len() - input.len();
|
let end_idx = all_bytes.len() - input.len();
|
||||||
@@ -269,6 +264,7 @@ impl EventDetails {
|
|||||||
end_idx,
|
end_idx,
|
||||||
all_bytes,
|
all_bytes,
|
||||||
metadata,
|
metadata,
|
||||||
|
topics,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,6 +381,11 @@ impl EventDetails {
|
|||||||
&self.metadata,
|
&self.metadata,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the topics associated with this event.
|
||||||
|
pub fn topics(&self) -> &[T::Hash] {
|
||||||
|
&self.topics
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Details for the given event plucked from the metadata.
|
/// Details for the given event plucked from the metadata.
|
||||||
@@ -467,14 +468,21 @@ pub(crate) mod test_utils {
|
|||||||
topics: Vec<<SubstrateConfig as Config>::Hash>,
|
topics: Vec<<SubstrateConfig as Config>::Hash>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<E: Encode> EventRecord<E> {
|
||||||
|
/// Create a new event record with the given phase, event, and topics.
|
||||||
|
pub fn new(phase: Phase, event: E, topics: Vec<<SubstrateConfig as Config>::Hash>) -> Self {
|
||||||
|
Self {
|
||||||
|
phase,
|
||||||
|
event: AllEvents::Test(event),
|
||||||
|
topics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Build an EventRecord, which encoded events in the format expected
|
/// Build an EventRecord, which encoded events in the format expected
|
||||||
/// to be handed back from storage queries to System.Events.
|
/// to be handed back from storage queries to System.Events.
|
||||||
pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
|
pub fn event_record<E: Encode>(phase: Phase, event: E) -> EventRecord<E> {
|
||||||
EventRecord {
|
EventRecord::new(phase, event, vec![])
|
||||||
phase,
|
|
||||||
event: AllEvents::Test(event),
|
|
||||||
topics: vec![],
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Build fake metadata consisting of a single pallet that knows
|
/// Build fake metadata consisting of a single pallet that knows
|
||||||
@@ -564,10 +572,12 @@ pub(crate) mod test_utils {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{
|
use super::{
|
||||||
test_utils::{event_record, events, events_raw, AllEvents},
|
test_utils::{event_record, events, events_raw, AllEvents, EventRecord},
|
||||||
*,
|
*,
|
||||||
};
|
};
|
||||||
|
use crate::SubstrateConfig;
|
||||||
use codec::Encode;
|
use codec::Encode;
|
||||||
|
use primitive_types::H256;
|
||||||
use scale_info::TypeInfo;
|
use scale_info::TypeInfo;
|
||||||
use scale_value::Value;
|
use scale_value::Value;
|
||||||
|
|
||||||
@@ -596,7 +606,7 @@ mod tests {
|
|||||||
// Just for convenience, pass in the metadata type constructed
|
// Just for convenience, pass in the metadata type constructed
|
||||||
// by the `metadata` function above to simplify caller code.
|
// by the `metadata` function above to simplify caller code.
|
||||||
metadata: &Metadata,
|
metadata: &Metadata,
|
||||||
actual: EventDetails,
|
actual: EventDetails<SubstrateConfig>,
|
||||||
expected: TestRawEventDetails,
|
expected: TestRawEventDetails,
|
||||||
) {
|
) {
|
||||||
let types = &metadata.types();
|
let types = &metadata.types();
|
||||||
@@ -950,4 +960,36 @@ mod tests {
|
|||||||
);
|
);
|
||||||
assert!(event_details.next().is_none());
|
assert!(event_details.next().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn topics() {
|
||||||
|
#[derive(Clone, Debug, PartialEq, Decode, Encode, TypeInfo, scale_decode::DecodeAsType)]
|
||||||
|
enum Event {
|
||||||
|
A(u8, bool, Vec<String>),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create fake metadata that knows about our single event, above:
|
||||||
|
let metadata = metadata::<Event>();
|
||||||
|
|
||||||
|
// Encode our events in the format we expect back from a node, and
|
||||||
|
// construct an Events object to iterate them:
|
||||||
|
let event = Event::A(1, true, vec!["Hi".into()]);
|
||||||
|
let topics = vec![H256::from_low_u64_le(123), H256::from_low_u64_le(456)];
|
||||||
|
let events = events::<Event>(
|
||||||
|
metadata,
|
||||||
|
vec![EventRecord::new(
|
||||||
|
Phase::ApplyExtrinsic(123),
|
||||||
|
event,
|
||||||
|
topics.clone(),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
|
||||||
|
let ev = events
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.expect("one event expected")
|
||||||
|
.expect("event should be extracted OK");
|
||||||
|
|
||||||
|
assert_eq!(topics, ev.topics());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user