diff --git a/src/api/mod.rs b/src/api/mod.rs index d4c4dd946..13d88c0a4 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -15,7 +15,8 @@ */ -use ac_node_api::events::RawEventDetails; +use crate::error::FailedExtrinsicError; +use ac_node_api::{events::RawEventDetails, EventDetails, Metadata}; use alloc::{string::String, vec::Vec}; use codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; @@ -60,6 +61,27 @@ impl ExtrinsicReport { ) -> Self { Self { extrinsic_hash, block_hash, status, events } } + + pub fn add_events(&mut self, events: Vec>) { + self.events = Some(events.into_iter().map(|event| event.to_raw()).collect()); + } + + pub fn status_based_on_events(&self, metadata: &Metadata) -> Result<()> { + if self.events.is_none() { + return Err(Error::Other("Report does not contain any events".into())) + } + // Check if the extrinsic was successful or not. + let events = self.events.as_ref().unwrap(); + for event in events { + if let Some(dispatch_error) = event.get_associated_dispatch_error(metadata) { + return Err(Error::FailedExtrinsic(FailedExtrinsicError::new( + dispatch_error, + self.encode(), + ))) + } + } + Ok(()) + } } /// Simplified TransactionStatus to allow the user to choose until when to watch diff --git a/src/api/rpc_api/author.rs b/src/api/rpc_api/author.rs index c9c345877..d67097df8 100644 --- a/src/api/rpc_api/author.rs +++ b/src/api/rpc_api/author.rs @@ -15,7 +15,6 @@ use crate::{ api::{rpc_api::events::FetchEvents, Error, Result}, - error::FailedExtrinsicError, rpc::{HandleSubscription, Request, Subscribe}, Api, ExtrinsicReport, TransactionStatus, XtStatus, }; @@ -283,6 +282,7 @@ where return Ok(report) } self.populate_events(&mut report).await?; + report.status_based_on_events(self.metadata())?; return Ok(report); } @@ -293,22 +293,7 @@ where let block_hash = report.block_hash.ok_or(Error::BlockHashNotFound)?; let extrinsic_events = self.fetch_events_for_extrinsic(block_hash, report.extrinsic_hash).await?; - - // Check if the extrinsic was successful or not. - let mut maybe_dispatch_error = None; - for event in &extrinsic_events { - if let Some(dispatch_error) = event.get_associated_dispatch_error() { - maybe_dispatch_error = Some(dispatch_error); - break - } - } - report.events = Some(extrinsic_events.into_iter().map(|event| event.to_raw()).collect()); - if let Some(dispatch_error) = maybe_dispatch_error { - return Err(Error::FailedExtrinsic(FailedExtrinsicError::new( - dispatch_error, - report.encode(), - ))) - } + report.add_events(extrinsic_events); Ok(()) } diff --git a/testing/async/examples/author_tests.rs b/testing/async/examples/author_tests.rs index 2e9fa1f41..22a2d6710 100644 --- a/testing/async/examples/author_tests.rs +++ b/testing/async/examples/author_tests.rs @@ -192,9 +192,13 @@ async fn test_submit_and_watch_extrinsic_until_in_block_without_events( assert!(report.block_hash.is_some()); assert!(report.events.is_none()); + // Should fail without events + assert!(report.status_based_on_events(&api.metadata()).is_err()); + // Now we fetch the events separately api.populate_events(&mut report).await.unwrap(); assert!(report.events.is_some()); + assert!(report.status_based_on_events(&api.metadata()).is_ok()); let events = report.events.as_ref().unwrap(); assert_associated_events_match_expected(&events);