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	let params = rpc_params![block_id, options];
24	let value: Vec<ExtrinsicInformation> = client.request("system_fetchExtrinsicsV1", params).await?;
25	let value: Vec<ExtrinsicInfo> = value.into_iter().map(|x| x.into()).collect();
26	Ok(value)
27}
28
29#[derive(Clone, Default)]
30pub struct Options {
31	pub transaction_filter: ExtrinsicFilter,
32	pub ss58_address: Option<String>,
33	pub app_id: Option<u32>,
34	pub nonce: Option<u32>,
35	pub encode_as: EncodeSelector,
36}
37
38#[derive(Debug, Clone, Default, Copy, Serialize, Deserialize)]
39#[repr(u8)]
40pub enum EncodeSelector {
41	None = 0,
42	Call = 1,
43	#[default]
44	Extrinsic = 2,
45}
46
47#[derive(Debug, Clone)]
48pub struct ExtrinsicInfo {
49	// Hex string encoded
50	pub data: Option<String>,
51	pub ext_hash: H256,
52	pub ext_index: u32,
53	pub pallet_id: u8,
54	pub variant_id: u8,
55	pub signer_payload: Option<SignerPayload>,
56}
57
58impl From<ExtrinsicInformation> for ExtrinsicInfo {
59	fn from(value: ExtrinsicInformation) -> Self {
60		Self {
61			data: value.encoded,
62			ext_hash: value.tx_hash,
63			ext_index: value.tx_index,
64			pallet_id: value.pallet_id,
65			variant_id: value.call_id,
66			signer_payload: value.signature,
67		}
68	}
69}
70
71#[derive(Debug, Default, Clone, Serialize, Deserialize)]
72pub struct SignerPayload {
73	pub ss58_address: Option<String>,
74	pub nonce: u32,
75	pub app_id: u32,
76	pub mortality: Option<(u64, u64)>,
77}
78
79#[derive(Debug, Clone, Serialize, Deserialize)]
80pub enum ExtrinsicFilter {
81	All,
82	TxHash(Vec<H256>),
83	TxIndex(Vec<u32>),
84	Pallet(Vec<u8>),
85	PalletCall(Vec<(u8, u8)>),
86}
87
88impl ExtrinsicFilter {
89	pub fn new() -> Self {
90		Self::default()
91	}
92}
93
94impl Default for ExtrinsicFilter {
95	fn default() -> Self {
96		Self::All
97	}
98}
99
100impl TryFrom<String> for ExtrinsicFilter {
101	type Error = String;
102
103	fn try_from(value: String) -> Result<Self, Self::Error> {
104		Self::try_from(value.as_str())
105	}
106}
107
108impl TryFrom<&String> for ExtrinsicFilter {
109	type Error = String;
110
111	fn try_from(value: &String) -> Result<Self, Self::Error> {
112		Self::try_from(value.as_str())
113	}
114}
115
116impl TryFrom<&str> for ExtrinsicFilter {
117	type Error = String;
118
119	fn try_from(value: &str) -> Result<Self, Self::Error> {
120		let h256 = H256::from_str(value).map_err(|x| x.to_string())?;
121		Ok(Self::TxHash(vec![h256]))
122	}
123}
124
125impl From<H256> for ExtrinsicFilter {
126	fn from(value: H256) -> Self {
127		Self::TxHash(vec![value])
128	}
129}
130
131impl From<u32> for ExtrinsicFilter {
132	fn from(value: u32) -> Self {
133		Self::TxIndex(vec![value])
134	}
135}
136
137impl From<u8> for ExtrinsicFilter {
138	fn from(value: u8) -> Self {
139		Self::Pallet(vec![value])
140	}
141}
142
143impl From<&[u8]> for ExtrinsicFilter {
144	fn from(value: &[u8]) -> Self {
145		Self::Pallet(value.to_vec())
146	}
147}
148
149impl From<(u8, u8)> for ExtrinsicFilter {
150	fn from(value: (u8, u8)) -> Self {
151		Self::PalletCall(vec![value])
152	}
153}
154
155impl From<&[(u8, u8)]> for ExtrinsicFilter {
156	fn from(value: &[(u8, u8)]) -> Self {
157		Self::PalletCall(value.to_vec())
158	}
159}
160
161impl From<Vec<(u8, u8)>> for ExtrinsicFilter {
162	fn from(value: Vec<(u8, u8)>) -> Self {
163		Self::PalletCall(value)
164	}
165}
166
167#[derive(Clone, Default, Serialize, Deserialize)]
168struct RpcOptions {
169	pub filter: Filter,
170	pub encode_selector: Option<EncodeSelector>,
171}
172
173#[derive(Default, Clone, Serialize, Deserialize)]
174struct Filter {
175	pub transaction: Option<ExtrinsicFilter>,
176	pub signature: SignatureFilter,
177}
178
179#[derive(Default, Clone, Serialize, Deserialize)]
180struct SignatureFilter {
181	pub ss58_address: Option<String>,
182	pub app_id: Option<u32>,
183	pub nonce: Option<u32>,
184}
185
186// This is struct is supposed to be private but is made public
187// for our tests to work.
188//
189// It is not dumb if it works. ¯\_(ツ)_/¯
190#[derive(Debug, Clone, Serialize, Deserialize, Default)]
191pub struct ExtrinsicInformation {
192	// Hex string encoded
193	pub encoded: Option<String>,
194	pub tx_hash: H256,
195	pub tx_index: u32,
196	pub pallet_id: u8,
197	pub call_id: u8,
198	pub signature: Option<SignerPayload>,
199}