avail_rust_core/rpc/system/
fetch_extrinsics.rs

1use crate::{HashNumber, rpc::Error};
2use primitive_types::H256;
3use serde::{Deserialize, Serialize};
4use std::str::FromStr;
5use subxt_rpcs::{RpcClient, rpc_params};
6
7pub async fn fetch_extrinsics_v1(
8	client: &RpcClient,
9	block_id: HashNumber,
10	options: &Options,
11) -> Result<Vec<ExtrinsicInfo>, Error> {
12	let options: RpcOptions = RpcOptions {
13		filter: Filter {
14			transaction: Some(options.transaction_filter.clone()),
15			signature: SignatureFilter {
16				ss58_address: options.ss58_address.clone(),
17				app_id: options.app_id,
18				nonce: options.nonce,
19			},
20		},
21		encode_selector: Some(options.encode_as),
22	};
23
24	let params = rpc_params![block_id, options];
25	let value: Vec<ExtrinsicInformation> = client.request("system_fetchExtrinsicsV1", params).await?;
26	let value: Vec<ExtrinsicInfo> = value.into_iter().map(|x| x.into()).collect();
27	Ok(value)
28}
29
30#[derive(Debug, Default, Clone)]
31pub struct Options {
32	pub transaction_filter: ExtrinsicFilter,
33	pub ss58_address: Option<String>,
34	pub app_id: Option<u32>,
35	pub nonce: Option<u32>,
36	pub encode_as: EncodeSelector,
37}
38
39impl Options {
40	pub fn new() -> Self {
41		Self::default()
42	}
43
44	pub fn nonce(mut self, value: u32) -> Self {
45		self.nonce = Some(value);
46		self
47	}
48
49	pub fn app_id(mut self, value: u32) -> Self {
50		self.app_id = Some(value);
51		self
52	}
53
54	pub fn ss58_address(mut self, value: impl Into<String>) -> Self {
55		self.ss58_address = Some(value.into());
56		self
57	}
58
59	pub fn filter(mut self, value: impl Into<ExtrinsicFilter>) -> Self {
60		self.transaction_filter = value.into();
61		self
62	}
63
64	pub fn encode_as(mut self, value: EncodeSelector) -> Self {
65		self.encode_as = value;
66		self
67	}
68}
69
70#[derive(Debug, Clone, Default, Copy, Serialize, Deserialize)]
71#[repr(u8)]
72pub enum EncodeSelector {
73	None = 0,
74	Call = 1,
75	#[default]
76	Extrinsic = 2,
77}
78
79#[derive(Debug, Clone)]
80pub struct ExtrinsicInfo {
81	// Hex string encoded
82	pub data: Option<String>,
83	pub ext_hash: H256,
84	pub ext_index: u32,
85	pub pallet_id: u8,
86	pub variant_id: u8,
87	pub signer_payload: Option<SignerPayload>,
88}
89
90impl From<ExtrinsicInformation> for ExtrinsicInfo {
91	fn from(value: ExtrinsicInformation) -> Self {
92		Self {
93			data: value.encoded,
94			ext_hash: value.tx_hash,
95			ext_index: value.tx_index,
96			pallet_id: value.pallet_id,
97			variant_id: value.call_id,
98			signer_payload: value.signature,
99		}
100	}
101}
102
103#[derive(Debug, Default, Clone, Serialize, Deserialize)]
104pub struct SignerPayload {
105	pub app_id: u32,
106	pub nonce: u32,
107	pub ss58_address: Option<String>,
108	pub mortality: Option<(u64, u64)>,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub enum ExtrinsicFilter {
113	All,
114	TxHash(Vec<H256>),
115	TxIndex(Vec<u32>),
116	Pallet(Vec<u8>),
117	PalletCall(Vec<(u8, u8)>),
118}
119
120impl ExtrinsicFilter {
121	pub fn new() -> Self {
122		Self::default()
123	}
124}
125
126impl Default for ExtrinsicFilter {
127	fn default() -> Self {
128		Self::All
129	}
130}
131
132impl TryFrom<String> for ExtrinsicFilter {
133	type Error = String;
134
135	fn try_from(value: String) -> Result<Self, Self::Error> {
136		Self::try_from(value.as_str())
137	}
138}
139
140impl TryFrom<&String> for ExtrinsicFilter {
141	type Error = String;
142
143	fn try_from(value: &String) -> Result<Self, Self::Error> {
144		Self::try_from(value.as_str())
145	}
146}
147
148impl TryFrom<&str> for ExtrinsicFilter {
149	type Error = String;
150
151	fn try_from(value: &str) -> Result<Self, Self::Error> {
152		let h256 = H256::from_str(value).map_err(|x| x.to_string())?;
153		Ok(Self::TxHash(vec![h256]))
154	}
155}
156
157impl From<H256> for ExtrinsicFilter {
158	fn from(value: H256) -> Self {
159		Self::TxHash(vec![value])
160	}
161}
162
163impl From<Vec<H256>> for ExtrinsicFilter {
164	fn from(value: Vec<H256>) -> Self {
165		Self::TxHash(value)
166	}
167}
168
169impl From<&Vec<H256>> for ExtrinsicFilter {
170	fn from(value: &Vec<H256>) -> Self {
171		Self::TxHash(value.clone())
172	}
173}
174
175impl From<&[H256]> for ExtrinsicFilter {
176	fn from(value: &[H256]) -> Self {
177		Self::TxHash(value.to_vec())
178	}
179}
180
181impl From<u32> for ExtrinsicFilter {
182	fn from(value: u32) -> Self {
183		Self::TxIndex(vec![value])
184	}
185}
186
187impl From<Vec<u32>> for ExtrinsicFilter {
188	fn from(value: Vec<u32>) -> Self {
189		Self::TxIndex(value)
190	}
191}
192
193impl From<&Vec<u32>> for ExtrinsicFilter {
194	fn from(value: &Vec<u32>) -> Self {
195		Self::TxIndex(value.clone())
196	}
197}
198
199impl From<&[u32]> for ExtrinsicFilter {
200	fn from(value: &[u32]) -> Self {
201		Self::TxIndex(value.to_vec())
202	}
203}
204
205impl From<u8> for ExtrinsicFilter {
206	fn from(value: u8) -> Self {
207		Self::Pallet(vec![value])
208	}
209}
210
211impl From<&[u8]> for ExtrinsicFilter {
212	fn from(value: &[u8]) -> Self {
213		Self::Pallet(value.to_vec())
214	}
215}
216
217impl From<Vec<u8>> for ExtrinsicFilter {
218	fn from(value: Vec<u8>) -> Self {
219		Self::Pallet(value)
220	}
221}
222
223impl From<&Vec<u8>> for ExtrinsicFilter {
224	fn from(value: &Vec<u8>) -> Self {
225		Self::Pallet(value.clone())
226	}
227}
228
229impl From<(u8, u8)> for ExtrinsicFilter {
230	fn from(value: (u8, u8)) -> Self {
231		Self::PalletCall(vec![value])
232	}
233}
234
235impl From<&[(u8, u8)]> for ExtrinsicFilter {
236	fn from(value: &[(u8, u8)]) -> Self {
237		Self::PalletCall(value.to_vec())
238	}
239}
240
241impl From<Vec<(u8, u8)>> for ExtrinsicFilter {
242	fn from(value: Vec<(u8, u8)>) -> Self {
243		Self::PalletCall(value)
244	}
245}
246
247impl From<&Vec<(u8, u8)>> for ExtrinsicFilter {
248	fn from(value: &Vec<(u8, u8)>) -> Self {
249		Self::PalletCall(value.clone())
250	}
251}
252
253#[derive(Debug, Clone, Default, Serialize, Deserialize)]
254struct RpcOptions {
255	pub filter: Filter,
256	pub encode_selector: Option<EncodeSelector>,
257}
258
259#[derive(Debug, Default, Clone, Serialize, Deserialize)]
260struct Filter {
261	pub transaction: Option<ExtrinsicFilter>,
262	pub signature: SignatureFilter,
263}
264
265#[derive(Debug, Default, Clone, Serialize, Deserialize)]
266struct SignatureFilter {
267	pub ss58_address: Option<String>,
268	pub app_id: Option<u32>,
269	pub nonce: Option<u32>,
270}
271
272// This is struct is supposed to be private but is made public
273// for our tests to work.
274//
275// It is not dumb if it works. ¯\_(ツ)_/¯
276#[derive(Debug, Clone, Serialize, Deserialize, Default)]
277pub struct ExtrinsicInformation {
278	// Hex string encoded
279	pub encoded: Option<String>,
280	pub tx_hash: H256,
281	pub tx_index: u32,
282	pub pallet_id: u8,
283	pub call_id: u8,
284	pub signature: Option<SignerPayload>,
285}