mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 11:07:56 +00:00
Add hooks to register event types for decoding (#227)
* Global registration of type segmenters for event decoding * Perform type sizes check when building client * Introduce EventTypeRegistry for global runtime type sizes * Fmt * Register runtime type sizes on creation of EventTypeRegistry * Register more default dispatch types * Add missing type sizes * fmt * Fix up register_type_size builder method * Update doc comments * Make register_default_type_sizes public * Don't allow duplicate registered types * Remove call to supertraits type registration, done manually in Runtime * Fix tests and warnings * Fix duplicate type registration * Fmt * review: use is_empty() Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com> * Add panic docs Co-authored-by: Niklas Adolfsson <niklasadolfsson1@gmail.com>
This commit is contained in:
+63
-15
@@ -49,7 +49,10 @@ pub use substrate_subxt_client as client;
|
||||
pub use sp_core;
|
||||
pub use sp_runtime;
|
||||
|
||||
use codec::Decode;
|
||||
use codec::{
|
||||
Codec,
|
||||
Decode,
|
||||
};
|
||||
use futures::future;
|
||||
use jsonrpsee::client::Subscription;
|
||||
use sp_core::{
|
||||
@@ -76,6 +79,7 @@ mod subscription;
|
||||
pub use crate::{
|
||||
error::Error,
|
||||
events::{
|
||||
EventTypeRegistry,
|
||||
EventsDecoder,
|
||||
RawEvent,
|
||||
},
|
||||
@@ -115,20 +119,22 @@ use crate::{
|
||||
/// ClientBuilder for constructing a Client.
|
||||
#[derive(Default)]
|
||||
pub struct ClientBuilder<T: Runtime> {
|
||||
_marker: std::marker::PhantomData<T>,
|
||||
url: Option<String>,
|
||||
client: Option<jsonrpsee::Client>,
|
||||
page_size: Option<u32>,
|
||||
event_type_registry: EventTypeRegistry<T>,
|
||||
skip_type_sizes_check: bool,
|
||||
}
|
||||
|
||||
impl<T: Runtime> ClientBuilder<T> {
|
||||
/// Creates a new ClientBuilder.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
_marker: std::marker::PhantomData,
|
||||
url: None,
|
||||
client: None,
|
||||
page_size: None,
|
||||
event_type_registry: EventTypeRegistry::new(),
|
||||
skip_type_sizes_check: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,8 +156,30 @@ impl<T: Runtime> ClientBuilder<T> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Register a custom type segmenter, for consuming types in events where the size cannot
|
||||
/// be inferred from the metadata.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If there is already a type size registered with this name.
|
||||
pub fn register_type_size<U>(mut self, name: &str) -> Self
|
||||
where
|
||||
U: Codec + Send + Sync + 'static,
|
||||
{
|
||||
self.event_type_registry.register_type_size::<U>(name);
|
||||
self
|
||||
}
|
||||
|
||||
/// Disable the check for missing type sizes on `build`.
|
||||
///
|
||||
/// *WARNING* can lead to runtime errors if receiving events with unknown types.
|
||||
pub fn skip_type_sizes_check(mut self) -> Self {
|
||||
self.skip_type_sizes_check = false;
|
||||
self
|
||||
}
|
||||
|
||||
/// Creates a new Client.
|
||||
pub async fn build(self) -> Result<Client<T>, Error> {
|
||||
pub async fn build<'a>(self) -> Result<Client<T>, Error> {
|
||||
let client = if let Some(client) = self.client {
|
||||
client
|
||||
} else {
|
||||
@@ -170,10 +198,33 @@ impl<T: Runtime> ClientBuilder<T> {
|
||||
rpc.system_properties(),
|
||||
)
|
||||
.await;
|
||||
let metadata = metadata?;
|
||||
|
||||
if let Err(missing) = self.event_type_registry.check_missing_type_sizes(&metadata)
|
||||
{
|
||||
if self.skip_type_sizes_check {
|
||||
log::warn!(
|
||||
"The following types do not have registered type segmenters: {:?} \
|
||||
If any events containing these types are received, this can cause a \
|
||||
`TypeSizeUnavailable` error and prevent decoding the actual event \
|
||||
being listened for.\
|
||||
\
|
||||
Use `ClientBuilder::register_type_size` to register missing type sizes.",
|
||||
missing
|
||||
);
|
||||
} else {
|
||||
return Err(Error::MissingTypeSizes(missing.into_iter().collect()))
|
||||
}
|
||||
}
|
||||
|
||||
let events_decoder =
|
||||
EventsDecoder::new(metadata.clone(), self.event_type_registry);
|
||||
|
||||
Ok(Client {
|
||||
rpc,
|
||||
genesis_hash: genesis_hash?,
|
||||
metadata: metadata?,
|
||||
metadata,
|
||||
events_decoder,
|
||||
properties: properties.unwrap_or_else(|_| Default::default()),
|
||||
runtime_version: runtime_version?,
|
||||
_marker: PhantomData,
|
||||
@@ -187,6 +238,7 @@ pub struct Client<T: Runtime> {
|
||||
rpc: Rpc<T>,
|
||||
genesis_hash: T::Hash,
|
||||
metadata: Metadata,
|
||||
events_decoder: EventsDecoder<T>,
|
||||
properties: SystemProperties,
|
||||
runtime_version: RuntimeVersion,
|
||||
_marker: PhantomData<(fn() -> T::Signature, T::Extra)>,
|
||||
@@ -199,6 +251,7 @@ impl<T: Runtime> Clone for Client<T> {
|
||||
rpc: self.rpc.clone(),
|
||||
genesis_hash: self.genesis_hash,
|
||||
metadata: self.metadata.clone(),
|
||||
events_decoder: self.events_decoder.clone(),
|
||||
properties: self.properties.clone(),
|
||||
runtime_version: self.runtime_version.clone(),
|
||||
_marker: PhantomData,
|
||||
@@ -466,12 +519,9 @@ impl<T: Runtime> Client<T> {
|
||||
Ok(signed)
|
||||
}
|
||||
|
||||
/// Returns an events decoder for a call.
|
||||
pub fn events_decoder<C: Call<T>>(&self) -> EventsDecoder<T> {
|
||||
let metadata = self.metadata().clone();
|
||||
let mut decoder = EventsDecoder::new(metadata);
|
||||
C::events_decoder(&mut decoder);
|
||||
decoder
|
||||
/// Returns the events decoder.
|
||||
pub fn events_decoder(&self) -> &EventsDecoder<T> {
|
||||
&self.events_decoder
|
||||
}
|
||||
|
||||
/// Create and submit an extrinsic and return corresponding Hash if successful
|
||||
@@ -486,10 +536,9 @@ impl<T: Runtime> Client<T> {
|
||||
pub async fn submit_and_watch_extrinsic(
|
||||
&self,
|
||||
extrinsic: UncheckedExtrinsic<T>,
|
||||
decoder: EventsDecoder<T>,
|
||||
) -> Result<ExtrinsicSuccess<T>, Error> {
|
||||
self.rpc
|
||||
.submit_and_watch_extrinsic(extrinsic, decoder)
|
||||
.submit_and_watch_extrinsic(extrinsic, &self.events_decoder)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -518,8 +567,7 @@ impl<T: Runtime> Client<T> {
|
||||
Send + Sync,
|
||||
{
|
||||
let extrinsic = self.create_signed(call, signer).await?;
|
||||
let decoder = self.events_decoder::<C>();
|
||||
self.submit_and_watch_extrinsic(extrinsic, decoder).await
|
||||
self.submit_and_watch_extrinsic(extrinsic).await
|
||||
}
|
||||
|
||||
/// Insert a key into the keystore.
|
||||
|
||||
Reference in New Issue
Block a user