From a7f342b61a1c146deb79555546f11d048e9a9077 Mon Sep 17 00:00:00 2001 From: Marko Petrlic Date: Mon, 23 Mar 2026 09:00:46 +0100 Subject: [PATCH] Updated custom extrinsic rpc interface --- client/src/block/extrinsic.rs | 77 +++++++++++++----------------- client/src/chain/api.rs | 8 ++-- client/src/subscription/fetcher.rs | 10 ++-- client/src/subscription/mod.rs | 10 ++-- core/src/rpc/custom/extrinsics.rs | 10 ++-- core/src/rpc/custom/mod.rs | 2 +- core/src/rpc/mod.rs | 2 +- 7 files changed, 55 insertions(+), 64 deletions(-) diff --git a/client/src/block/extrinsic.rs b/client/src/block/extrinsic.rs index 61c6fc6b..7e677767 100644 --- a/client/src/block/extrinsic.rs +++ b/client/src/block/extrinsic.rs @@ -9,7 +9,7 @@ use crate::{ }; use avail_rust_core::{ Extrinsic, ExtrinsicDecodable, H256, HasHeader, HashNumber, MultiAddress, RpcError, avail, - rpc::{self, AllowedExtrinsic, DataFormat}, + rpc::{self, AllowedExtrinsic, DataFormat, Query}, substrate::extrinsic::Preamble, types::HashStringNumber, }; @@ -52,15 +52,14 @@ impl ExtrinsicsQuery { pub async fn first( &self, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + mut query: rpc::Query, ) -> Result, Error> { let at = self.ctx.hash_number()?; let chain = self.ctx.chain(); + query.max_items = Some(1); + query.reverse = false; - let mut result = chain - .extrinsics(at, allow_list, sig_filter, DataFormat::Extrinsic) - .await?; - + let mut result = chain.extrinsics(at, allow_list, query, DataFormat::Extrinsic).await?; let Some(info) = result.first_mut() else { return Ok(None); }; @@ -72,14 +71,14 @@ impl ExtrinsicsQuery { pub async fn last( &self, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + mut query: rpc::Query, ) -> Result, Error> { let at = self.ctx.hash_number()?; let chain = self.ctx.chain(); + query.max_items = Some(1); + query.reverse = true; - let mut result = chain - .extrinsics(at, allow_list, sig_filter, DataFormat::Extrinsic) - .await?; + let mut result = chain.extrinsics(at, allow_list, query, DataFormat::Extrinsic).await?; let Some(info) = result.last_mut() else { return Ok(None); }; @@ -91,14 +90,12 @@ impl ExtrinsicsQuery { pub async fn all( &self, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + query: rpc::Query, ) -> Result, Error> { let at = self.ctx.hash_number()?; let chain = self.ctx.chain(); - let extrinsics = chain - .extrinsics(at, allow_list, sig_filter, DataFormat::Extrinsic) - .await?; + let extrinsics = chain.extrinsics(at, allow_list, query, DataFormat::Extrinsic).await?; let mut result = Vec::with_capacity(extrinsics.len()); for info in extrinsics { @@ -109,14 +106,10 @@ impl ExtrinsicsQuery { Ok(result) } - pub async fn count( - &self, - allow_list: Option>, - sig_filter: rpc::SignatureFilter, - ) -> Result { + pub async fn count(&self, allow_list: Option>, query: rpc::Query) -> Result { let at = self.ctx.at.clone(); let chain = self.ctx.chain(); - let result = chain.extrinsics(at, allow_list, sig_filter, DataFormat::None).await?; + let result = chain.extrinsics(at, allow_list, query, DataFormat::None).await?; Ok(result.len()) } @@ -124,9 +117,10 @@ impl ExtrinsicsQuery { pub async fn exists( &self, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + mut query: rpc::Query, ) -> Result { - self.count(allow_list, sig_filter).await.map(|x| x > 0) + query.max_items = Some(1); + self.count(allow_list, query).await.map(|x| x > 0) } // ── Typed (_as) methods ───────────────────────────────────────────── @@ -159,13 +153,10 @@ impl ExtrinsicsQuery { inner::(self, extrinsic_id.into()).await } - pub async fn first_as( - &self, - sig_filter: rpc::SignatureFilter, - ) -> Result>, Error> { + pub async fn first_as(&self, query: rpc::Query) -> Result>, Error> { let allow_list = Some(vec![T::HEADER_INDEX.into()]); - let encoded = self.first(allow_list, sig_filter).await?; + let encoded = self.first(allow_list, query).await?; let Some(encoded) = encoded else { return Ok(None); }; @@ -173,13 +164,10 @@ impl ExtrinsicsQuery { Ok(Some(encoded.as_typed::()?)) } - pub async fn last_as( - &self, - sig_filter: rpc::SignatureFilter, - ) -> Result>, Error> { + pub async fn last_as(&self, query: rpc::Query) -> Result>, Error> { let allow_list = Some(vec![T::HEADER_INDEX.into()]); - let encoded = self.last(allow_list, sig_filter).await?; + let encoded = self.last(allow_list, query).await?; let Some(encoded) = encoded else { return Ok(None); }; @@ -187,13 +175,10 @@ impl ExtrinsicsQuery { Ok(Some(encoded.as_typed::()?)) } - pub async fn all_as( - &self, - sig_filter: rpc::SignatureFilter, - ) -> Result>, Error> { + pub async fn all_as(&self, query: rpc::Query) -> Result>, Error> { let allow_list = Some(vec![T::HEADER_INDEX.into()]); - let all = self.all(allow_list, sig_filter).await?; + let all = self.all(allow_list, query).await?; let mut result = Vec::with_capacity(all.len()); for encoded in all { result.push(encoded.as_typed::()?); @@ -206,7 +191,9 @@ impl ExtrinsicsQuery { /// Block 0 is the only block that does not have this extrinsic in it. pub async fn ext_timestamp(&self) -> Result, Error> { - let ext = self.first_as::(Default::default()).await?; + let mut query = Query::default(); + query.max_items = Some(1); + let ext = self.first_as::(query).await?; let Some(ext) = ext else { return Err(Error::NotFound(String::from("Timestamp Set extrinsic not found"))); }; @@ -217,8 +204,10 @@ impl ExtrinsicsQuery { pub async fn ext_submit_blob_txs_summary( &self, ) -> Result, Error> { + let mut query = Query::default(); + query.max_items = Some(1); let ext = self - .first_as::(Default::default()) + .first_as::(query) .await?; let Some(ext) = ext else { return Err(Error::NotFound(String::from("Data Availability Submit Blob Tx Summary extrinsic not found"))); @@ -230,9 +219,9 @@ impl ExtrinsicsQuery { pub async fn ext_failed_send_message_txs( &self, ) -> Result, Error> { - let ext = self - .first_as::(Default::default()) - .await?; + let mut query = Query::default(); + query.max_items = Some(1); + let ext = self.first_as::(query).await?; let Some(ext) = ext else { return Err(Error::NotFound(String::from("Vector Failed Send Message Txs extrinsic not found"))); }; @@ -244,12 +233,12 @@ impl ExtrinsicsQuery { pub async fn rpc( &self, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + query: rpc::Query, data_format: rpc::DataFormat, ) -> Result, Error> { self.ctx .chain() - .extrinsics(self.ctx.at.clone(), allow_list, sig_filter, data_format) + .extrinsics(self.ctx.at.clone(), allow_list, query, data_format) .await } diff --git a/client/src/chain/api.rs b/client/src/chain/api.rs index c3887b90..b6d5762a 100644 --- a/client/src/chain/api.rs +++ b/client/src/chain/api.rs @@ -630,14 +630,14 @@ impl Chain { &self, at: impl Into, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + query: rpc::Query, data_format: rpc::DataFormat, ) -> Result, Error> { async fn inner( c: &Chain, at: HashNumber, allow_list: Option>, - sig_filter: rpc::SignatureFilter, + query: rpc::Query, data_format: rpc::DataFormat, ) -> Result, Error> { retry!(c.should_retry_on_error(), { @@ -645,7 +645,7 @@ impl Chain { &c.client.rpc_client, at.into(), allow_list.clone(), - sig_filter.clone(), + query.clone(), data_format, ) .await @@ -655,7 +655,7 @@ impl Chain { let at = HashNumber::try_from(at.into()) .map_err(|e| Error::validation_with_op(error_ops::ErrorOperation::ChainFetchExtrinsics, e))?; - inner(self, at, allow_list, sig_filter, data_format).await + inner(self, at, allow_list, query, data_format).await } /// Pulls events for a block with optional filtering. diff --git a/client/src/subscription/fetcher.rs b/client/src/subscription/fetcher.rs index 2010c5f8..c5aa5b45 100644 --- a/client/src/subscription/fetcher.rs +++ b/client/src/subscription/fetcher.rs @@ -12,7 +12,7 @@ use async_trait::async_trait; use avail_rust_core::{ BlockInfo, HasHeader, grandpa::GrandpaJustification, - rpc::{AllowedEvents, AllowedExtrinsic, LegacyBlock, PhaseEvents, SignatureFilter}, + rpc::{AllowedEvents, AllowedExtrinsic, LegacyBlock, PhaseEvents, Query}, }; use codec::Decode; use std::marker::PhantomData; @@ -143,7 +143,7 @@ impl Fetcher for BlockEventsFetcher { /// Yields decoded extrinsics of type `T` for each block. #[derive(Clone)] pub struct ExtrinsicFetcher { - pub(crate) sig_filter: SignatureFilter, + pub(crate) query: Query, pub(crate) _phantom: PhantomData, } @@ -154,7 +154,7 @@ impl Fetcher for ExtrinsicFetcher { async fn fetch(&self, client: &Client, info: BlockInfo, retry: RetryPolicy) -> Result { let mut block = Block::new(client.clone(), info.hash).extrinsics(); block.set_retry_policy(retry); - block.all_as::(self.sig_filter.clone()).await + block.all_as::(self.query.clone()).await } fn is_empty(&self, value: &Self::Output) -> bool { @@ -170,7 +170,7 @@ impl Fetcher for ExtrinsicFetcher { #[derive(Debug, Clone)] pub struct UntypedExtrinsicFetcher { pub(crate) allow_list: Option>, - pub(crate) sig_filter: SignatureFilter, + pub(crate) query: Query, } #[async_trait] @@ -180,7 +180,7 @@ impl Fetcher for UntypedExtrinsicFetcher { async fn fetch(&self, client: &Client, info: BlockInfo, retry: RetryPolicy) -> Result { let mut block = Block::new(client.clone(), info.hash).extrinsics(); block.set_retry_policy(retry); - block.all(self.allow_list.clone(), self.sig_filter.clone()).await + block.all(self.allow_list.clone(), self.query.clone()).await } fn is_empty(&self, value: &Self::Output) -> bool { diff --git a/client/src/subscription/mod.rs b/client/src/subscription/mod.rs index b2ecee7a..0446743b 100644 --- a/client/src/subscription/mod.rs +++ b/client/src/subscription/mod.rs @@ -12,7 +12,7 @@ pub use sub::{BlockQueryMode, Subscription, SubscriptionItem}; use crate::Client; use avail_rust_core::{ HasHeader, - rpc::{AllowedEvents, AllowedExtrinsic, SignatureFilter}, + rpc::{AllowedEvents, AllowedExtrinsic, Query}, }; use codec::Decode; use std::marker::PhantomData; @@ -42,17 +42,17 @@ impl SubscribeApi { pub fn extrinsics( &self, - sig_filter: SignatureFilter, + query: Query, ) -> SubscriptionBuilder> { - SubscriptionBuilder::new(self.0.clone(), ExtrinsicFetcher { sig_filter, _phantom: PhantomData }) + SubscriptionBuilder::new(self.0.clone(), ExtrinsicFetcher { query, _phantom: PhantomData }) } pub fn untyped_extrinsics( &self, allow_list: Option>, - sig_filter: SignatureFilter, + query: Query, ) -> SubscriptionBuilder { - SubscriptionBuilder::new(self.0.clone(), UntypedExtrinsicFetcher { allow_list, sig_filter }) + SubscriptionBuilder::new(self.0.clone(), UntypedExtrinsicFetcher { allow_list, query }) } pub fn justification(&self) -> SubscriptionBuilder { diff --git a/core/src/rpc/custom/extrinsics.rs b/core/src/rpc/custom/extrinsics.rs index 245f8d64..29e80973 100644 --- a/core/src/rpc/custom/extrinsics.rs +++ b/core/src/rpc/custom/extrinsics.rs @@ -11,10 +11,10 @@ pub async fn fetch_extrinsics( client: &RpcClient, at: BlockId, allow_list: Option>, - sig_filter: SignatureFilter, + query: Query, data_format: DataFormat, ) -> Result, Error> { - let params = rpc_params![at, allow_list, sig_filter, data_format]; + let params = rpc_params![at, allow_list, query, data_format]; let value: Vec = client.request("custom_extrinsics", params).await?; Ok(value) } @@ -70,9 +70,11 @@ impl From<(u8, u8)> for AllowedExtrinsic { } #[derive(Debug, Default, Clone, Serialize, Deserialize)] -pub struct SignatureFilter { - pub account_id: Option, +pub struct Query { + pub address: Option, pub nonce: Option, + pub max_items: Option, + pub reverse: bool, } #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] diff --git a/core/src/rpc/custom/mod.rs b/core/src/rpc/custom/mod.rs index 0c54fbec..f1ba184c 100644 --- a/core/src/rpc/custom/mod.rs +++ b/core/src/rpc/custom/mod.rs @@ -6,7 +6,7 @@ use primitive_types::H256; use subxt_rpcs::{RpcClient, rpc_params}; pub use events::{AllowedEvents, PhaseEvents, RuntimeEvent, fetch_events}; -pub use extrinsics::{AllowedExtrinsic, DataFormat, Extrinsic, SignatureFilter, fetch_extrinsics}; +pub use extrinsics::{AllowedExtrinsic, DataFormat, Extrinsic, Query, fetch_extrinsics}; pub async fn get_block_number(client: &RpcClient, at: H256) -> Result, Error> { let params = rpc_params![at]; diff --git a/core/src/rpc/mod.rs b/core/src/rpc/mod.rs index c076561e..c8f7fc06 100644 --- a/core/src/rpc/mod.rs +++ b/core/src/rpc/mod.rs @@ -15,7 +15,7 @@ pub use error::Error; pub use super::AvailHeader; pub use chain::{Block, BlockJustification, LegacyBlock}; -pub use custom::{AllowedEvents, AllowedExtrinsic, DataFormat, Extrinsic, PhaseEvents, RuntimeEvent, SignatureFilter}; +pub use custom::{AllowedEvents, AllowedExtrinsic, DataFormat, Extrinsic, PhaseEvents, Query, RuntimeEvent}; use subxt_rpcs::{RpcClient, client::RpcParams}; pub async fn raw_call(