1use crate::client::{RpcClient, RpcSubscription, rpc_params};
8use crate::{Error, RpcConfig};
9use codec::Decode;
10use derive_where::derive_where;
11use frame_metadata::RuntimeMetadataPrefixed;
12use primitive_types::U256;
13use serde::{Deserialize, Serialize};
14
15#[derive_where(Clone, Debug)]
19pub struct LegacyRpcMethods<T> {
20 client: RpcClient,
21 _marker: std::marker::PhantomData<T>,
22}
23
24impl<T: RpcConfig> LegacyRpcMethods<T> {
25 pub fn new(client: RpcClient) -> Self {
27 LegacyRpcMethods {
28 client,
29 _marker: std::marker::PhantomData,
30 }
31 }
32
33 pub async fn state_get_storage(
35 &self,
36 key: &[u8],
37 hash: Option<T::Hash>,
38 ) -> Result<Option<StorageData>, Error> {
39 let params = rpc_params![to_hex(key), hash];
40 let data: Option<Bytes> = self.client.request("state_getStorage", params).await?;
41 Ok(data.map(|b| b.0))
42 }
43
44 pub async fn state_get_keys_paged(
48 &self,
49 key: &[u8],
50 count: u32,
51 start_key: Option<&[u8]>,
52 at: Option<T::Hash>,
53 ) -> Result<Vec<StorageKey>, Error> {
54 let start_key = start_key.map(to_hex);
55 let params = rpc_params![to_hex(key), count, start_key, at];
56 let data: Vec<Bytes> = self.client.request("state_getKeysPaged", params).await?;
57 Ok(data.into_iter().map(|b| b.0).collect())
58 }
59
60 pub async fn state_query_storage(
65 &self,
66 keys: impl IntoIterator<Item = &[u8]>,
67 from: T::Hash,
68 to: Option<T::Hash>,
69 ) -> Result<Vec<StorageChangeSet<T::Hash>>, Error> {
70 let keys: Vec<String> = keys.into_iter().map(to_hex).collect();
71 let params = rpc_params![keys, from, to];
72 self.client.request("state_queryStorage", params).await
73 }
74
75 pub async fn state_query_storage_at(
79 &self,
80 keys: impl IntoIterator<Item = &[u8]>,
81 at: Option<T::Hash>,
82 ) -> Result<Vec<StorageChangeSet<T::Hash>>, Error> {
83 let keys: Vec<String> = keys.into_iter().map(to_hex).collect();
84 let params = rpc_params![keys, at];
85 self.client.request("state_queryStorageAt", params).await
86 }
87
88 pub async fn genesis_hash(&self) -> Result<T::Hash, Error> {
90 let block_zero = 0u32;
91 let params = rpc_params![block_zero];
92 let genesis_hash: Option<T::Hash> =
93 self.client.request("chain_getBlockHash", params).await?;
94 genesis_hash.ok_or_else(|| Error::Client("Genesis hash not found".into()))
95 }
96
97 pub async fn state_get_metadata(
99 &self,
100 at: Option<T::Hash>,
101 ) -> Result<StateGetMetadataResponse, Error> {
102 let bytes: Bytes = self
103 .client
104 .request("state_getMetadata", rpc_params![at])
105 .await?;
106 Ok(StateGetMetadataResponse(bytes.0))
107 }
108
109 pub async fn system_health(&self) -> Result<SystemHealth, Error> {
111 self.client.request("system_health", rpc_params![]).await
112 }
113
114 pub async fn system_chain(&self) -> Result<String, Error> {
116 self.client.request("system_chain", rpc_params![]).await
117 }
118
119 pub async fn system_name(&self) -> Result<String, Error> {
121 self.client.request("system_name", rpc_params![]).await
122 }
123
124 pub async fn system_version(&self) -> Result<String, Error> {
126 self.client.request("system_version", rpc_params![]).await
127 }
128
129 pub async fn system_properties(&self) -> Result<SystemProperties, Error> {
131 self.client
132 .request("system_properties", rpc_params![])
133 .await
134 }
135
136 pub async fn system_account_next_index(&self, account_id: &T::AccountId) -> Result<u64, Error> {
140 self.client
141 .request("system_accountNextIndex", rpc_params![&account_id])
142 .await
143 }
144
145 pub async fn chain_get_header(
147 &self,
148 hash: Option<T::Hash>,
149 ) -> Result<Option<T::Header>, Error> {
150 let params = rpc_params![hash];
151 let header = self.client.request("chain_getHeader", params).await?;
152 Ok(header)
153 }
154
155 pub async fn chain_get_block_hash(
157 &self,
158 block_number: Option<BlockNumber>,
159 ) -> Result<Option<T::Hash>, Error> {
160 let params = rpc_params![block_number];
161 let block_hash = self.client.request("chain_getBlockHash", params).await?;
162 Ok(block_hash)
163 }
164
165 pub async fn chain_get_finalized_head(&self) -> Result<T::Hash, Error> {
167 let hash = self
168 .client
169 .request("chain_getFinalizedHead", rpc_params![])
170 .await?;
171 Ok(hash)
172 }
173
174 pub async fn chain_get_block(
176 &self,
177 hash: Option<T::Hash>,
178 ) -> Result<Option<BlockDetails<T>>, Error> {
179 let params = rpc_params![hash];
180 let block = self.client.request("chain_getBlock", params).await?;
181 Ok(block)
182 }
183
184 pub async fn dev_get_block_stats(
190 &self,
191 block_hash: T::Hash,
192 ) -> Result<Option<BlockStats>, Error> {
193 let params = rpc_params![block_hash];
194 let stats = self.client.request("dev_getBlockStats", params).await?;
195 Ok(stats)
196 }
197
198 pub async fn state_get_read_proof(
200 &self,
201 keys: impl IntoIterator<Item = &[u8]>,
202 hash: Option<T::Hash>,
203 ) -> Result<ReadProof<T::Hash>, Error> {
204 let keys: Vec<String> = keys.into_iter().map(to_hex).collect();
205 let params = rpc_params![keys, hash];
206 let proof = self.client.request("state_getReadProof", params).await?;
207 Ok(proof)
208 }
209
210 pub async fn state_get_runtime_version(
212 &self,
213 at: Option<T::Hash>,
214 ) -> Result<RuntimeVersion, Error> {
215 let params = rpc_params![at];
216 let version = self
217 .client
218 .request("state_getRuntimeVersion", params)
219 .await?;
220 Ok(version)
221 }
222
223 pub async fn chain_subscribe_new_heads(&self) -> Result<RpcSubscription<T::Header>, Error> {
225 let subscription = self
226 .client
227 .subscribe(
228 "chain_subscribeNewHeads",
232 rpc_params![],
233 "chain_unsubscribeNewHeads",
234 )
235 .await?;
236
237 Ok(subscription)
238 }
239
240 pub async fn chain_subscribe_all_heads(&self) -> Result<RpcSubscription<T::Header>, Error> {
242 let subscription = self
243 .client
244 .subscribe(
245 "chain_subscribeAllHeads",
249 rpc_params![],
250 "chain_unsubscribeAllHeads",
251 )
252 .await?;
253
254 Ok(subscription)
255 }
256
257 pub async fn chain_subscribe_finalized_heads(
264 &self,
265 ) -> Result<RpcSubscription<T::Header>, Error> {
266 let subscription = self
267 .client
268 .subscribe(
269 "chain_subscribeFinalizedHeads",
270 rpc_params![],
271 "chain_unsubscribeFinalizedHeads",
272 )
273 .await?;
274 Ok(subscription)
275 }
276
277 pub async fn state_subscribe_runtime_version(
280 &self,
281 ) -> Result<RpcSubscription<RuntimeVersion>, Error> {
282 let subscription = self
283 .client
284 .subscribe(
285 "state_subscribeRuntimeVersion",
286 rpc_params![],
287 "state_unsubscribeRuntimeVersion",
288 )
289 .await?;
290 Ok(subscription)
291 }
292
293 pub async fn author_submit_extrinsic(&self, extrinsic: &[u8]) -> Result<T::Hash, Error> {
295 let params = rpc_params![to_hex(extrinsic)];
296 let xt_hash = self
297 .client
298 .request("author_submitExtrinsic", params)
299 .await?;
300 Ok(xt_hash)
301 }
302
303 pub async fn author_submit_and_watch_extrinsic(
305 &self,
306 extrinsic: &[u8],
307 ) -> Result<RpcSubscription<TransactionStatus<T::Hash>>, Error> {
308 let params = rpc_params![to_hex(extrinsic)];
309 let subscription = self
310 .client
311 .subscribe(
312 "author_submitAndWatchExtrinsic",
313 params,
314 "author_unwatchExtrinsic",
315 )
316 .await?;
317 Ok(subscription)
318 }
319
320 pub async fn author_insert_key(
322 &self,
323 key_type: String,
324 suri: String,
325 public: Vec<u8>,
326 ) -> Result<(), Error> {
327 let params = rpc_params![key_type, suri, Bytes(public)];
328 self.client.request("author_insertKey", params).await
329 }
330
331 pub async fn author_rotate_keys(&self) -> Result<Vec<u8>, Error> {
333 let bytes: Bytes = self
334 .client
335 .request("author_rotateKeys", rpc_params![])
336 .await?;
337 Ok(bytes.0)
338 }
339
340 pub async fn author_has_session_keys(&self, session_keys: Vec<u8>) -> Result<bool, Error> {
346 let params = rpc_params![Bytes(session_keys)];
347 self.client.request("author_hasSessionKeys", params).await
348 }
349
350 pub async fn author_has_key(
354 &self,
355 public_key: Vec<u8>,
356 key_type: String,
357 ) -> Result<bool, Error> {
358 let params = rpc_params![Bytes(public_key), key_type];
359 self.client.request("author_hasKey", params).await
360 }
361
362 pub async fn state_call(
364 &self,
365 function: &str,
366 call_parameters: Option<&[u8]>,
367 at: Option<T::Hash>,
368 ) -> Result<Vec<u8>, Error> {
369 let call_parameters = call_parameters.unwrap_or_default();
370 let bytes: Bytes = self
371 .client
372 .request(
373 "state_call",
374 rpc_params![function, to_hex(call_parameters), at],
375 )
376 .await?;
377 Ok(bytes.0)
378 }
379
380 pub async fn dry_run(
384 &self,
385 encoded_signed: &[u8],
386 at: Option<T::Hash>,
387 ) -> Result<DryRunResultBytes, Error> {
388 let params = rpc_params![to_hex(encoded_signed), at];
389 let result_bytes: Bytes = self.client.request("system_dryRun", params).await?;
390 Ok(DryRunResultBytes(result_bytes.0))
391 }
392}
393
394pub struct StateGetMetadataResponse(Vec<u8>);
396
397impl StateGetMetadataResponse {
398 pub fn into_raw(self) -> Vec<u8> {
400 self.0
401 }
402 pub fn to_frame_metadata(
404 &self,
405 ) -> Result<frame_metadata::RuntimeMetadataPrefixed, codec::Error> {
406 RuntimeMetadataPrefixed::decode(&mut &*self.0)
407 }
408}
409
410pub type StorageKey = Vec<u8>;
412
413pub type StorageData = Vec<u8>;
415
416#[derive(Deserialize, Clone, Debug)]
418#[serde(rename_all = "camelCase")]
419pub struct SystemHealth {
420 pub peers: usize,
422 pub is_syncing: bool,
424 pub should_have_peers: bool,
428}
429
430pub type SystemProperties = serde_json::Map<String, serde_json::Value>;
432
433pub type BlockNumber = NumberOrHex;
435
436#[derive(Debug, Deserialize)]
438#[serde(bound = "T: RpcConfig")]
439pub struct BlockDetails<T: RpcConfig> {
440 pub block: Block<T>,
442 pub justifications: Option<Vec<BlockJustification>>,
444}
445
446#[derive(Debug, Deserialize)]
448pub struct Block<T: RpcConfig> {
449 pub header: T::Header,
451 pub extrinsics: Vec<Bytes>,
453}
454
455pub type BlockJustification = (ConsensusEngineId, EncodedJustification);
457pub type ConsensusEngineId = [u8; 4];
459pub type EncodedJustification = Vec<u8>;
461
462#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
465#[serde(rename_all = "camelCase")]
466pub struct RuntimeVersion {
467 pub spec_version: u32,
471
472 pub transaction_version: u32,
482
483 #[serde(flatten)]
485 pub other: std::collections::HashMap<String, serde_json::Value>,
486}
487
488#[derive(Debug, Deserialize)]
495#[serde(rename_all = "camelCase")]
496pub enum TransactionStatus<Hash> {
497 Future,
499 Ready,
501 Broadcast(Vec<String>),
503 InBlock(Hash),
505 Retracted(Hash),
507 FinalityTimeout(Hash),
510 Finalized(Hash),
512 Usurped(Hash),
515 Dropped,
517 Invalid,
519}
520
521#[derive(Debug, PartialEq, Eq)]
523pub enum DryRunResult<'a> {
524 Success,
526 DispatchError(&'a [u8]),
536 TransactionValidityError,
538}
539
540pub struct DryRunResultBytes(pub Vec<u8>);
543
544impl DryRunResultBytes {
545 pub fn into_dry_run_result(&self) -> Result<DryRunResult<'_>, DryRunDecodeError> {
547 let bytes = &*self.0;
550
551 if bytes.len() < 2 {
554 return Err(DryRunDecodeError::WrongNumberOfBytes);
555 }
556
557 if bytes[0] == 0 && bytes[1] == 0 {
558 Ok(DryRunResult::Success)
560 } else if bytes[0] == 0 && bytes[1] == 1 {
561 Ok(DryRunResult::DispatchError(&bytes[2..]))
563 } else if bytes[0] == 1 {
564 Ok(DryRunResult::TransactionValidityError)
566 } else {
567 Err(DryRunDecodeError::InvalidBytes)
569 }
570 }
571}
572
573pub enum DryRunDecodeError {
575 WrongNumberOfBytes,
577 InvalidBytes,
579}
580
581#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
583#[serde(rename_all = "camelCase")]
584pub struct StorageChangeSet<Hash> {
585 pub block: Hash,
587 pub changes: Vec<(Bytes, Option<Bytes>)>,
589}
590
591#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
593#[serde(rename_all = "camelCase")]
594pub struct BlockStats {
595 pub witness_len: u64,
597 pub witness_compact_len: u64,
599 pub block_len: u64,
604 pub num_extrinsics: u64,
609}
610
611#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
618#[serde(rename_all = "camelCase")]
619pub struct ReadProof<Hash> {
620 pub at: Hash,
622 pub proof: Vec<Bytes>,
624}
625
626#[derive(Copy, Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
635#[serde(untagged)]
636pub enum NumberOrHex {
637 Number(u64),
639 Hex(U256),
641}
642
643impl NumberOrHex {
644 pub fn into_u256(self) -> U256 {
646 match self {
647 NumberOrHex::Number(n) => n.into(),
648 NumberOrHex::Hex(h) => h,
649 }
650 }
651}
652
653impl From<NumberOrHex> for U256 {
654 fn from(num_or_hex: NumberOrHex) -> U256 {
655 num_or_hex.into_u256()
656 }
657}
658
659macro_rules! into_number_or_hex {
660 ($($t: ty)+) => {
661 $(
662 impl From<$t> for NumberOrHex {
663 fn from(x: $t) -> Self {
664 NumberOrHex::Number(x.into())
665 }
666 }
667 )+
668 }
669}
670into_number_or_hex!(u8 u16 u32 u64);
671
672impl From<u128> for NumberOrHex {
673 fn from(n: u128) -> Self {
674 NumberOrHex::Hex(n.into())
675 }
676}
677
678impl From<U256> for NumberOrHex {
679 fn from(n: U256) -> Self {
680 NumberOrHex::Hex(n)
681 }
682}
683
684fn to_hex(bytes: impl AsRef<[u8]>) -> String {
686 format!("0x{}", hex::encode(bytes.as_ref()))
687}
688
689#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Hash, PartialOrd, Ord, Debug)]
691pub struct Bytes(#[serde(with = "impl_serde::serialize")] pub Vec<u8>);
692impl std::ops::Deref for Bytes {
693 type Target = [u8];
694 fn deref(&self) -> &[u8] {
695 &self.0[..]
696 }
697}
698impl From<Vec<u8>> for Bytes {
699 fn from(s: Vec<u8>) -> Self {
700 Bytes(s)
701 }
702}