1use crate::Hash;
10use crate::client::{RpcClient, RpcSubscription, rpc_params};
11use crate::{Error, RpcConfig};
12use derive_where::derive_where;
13use futures::{Stream, StreamExt};
14use serde::{Deserialize, Deserializer, Serialize};
15use std::collections::{HashMap, VecDeque};
16use std::task::Poll;
17
18#[derive_where(Clone, Debug)]
22pub struct ChainHeadRpcMethods<T> {
23 client: RpcClient,
24 _marker: std::marker::PhantomData<T>,
25}
26
27impl<T: RpcConfig> ChainHeadRpcMethods<T> {
28 pub fn new(client: RpcClient) -> Self {
30 ChainHeadRpcMethods {
31 client,
32 _marker: std::marker::PhantomData,
33 }
34 }
35
36 pub async fn chainhead_v1_follow(
50 &self,
51 with_runtime: bool,
52 ) -> Result<FollowSubscription<T::Hash>, Error> {
53 let sub = self
54 .client
55 .subscribe(
56 "chainHead_v1_follow",
57 rpc_params![with_runtime],
58 "chainHead_v1_unfollow",
59 )
60 .await?;
61
62 Ok(FollowSubscription { sub, done: false })
63 }
64
65 pub async fn chainhead_v1_continue(
71 &self,
72 follow_subscription: &str,
73 operation_id: &str,
74 ) -> Result<(), Error> {
75 self.client
76 .request(
77 "chainHead_v1_continue",
78 rpc_params![follow_subscription, operation_id],
79 )
80 .await
81 }
82
83 pub async fn chainhead_v1_stop_operation(
89 &self,
90 follow_subscription: &str,
91 operation_id: &str,
92 ) -> Result<(), Error> {
93 self.client
94 .request(
95 "chainHead_v1_stopOperation",
96 rpc_params![follow_subscription, operation_id],
97 )
98 .await
99 }
100
101 pub async fn chainhead_v1_body(
111 &self,
112 subscription_id: &str,
113 hash: T::Hash,
114 ) -> Result<MethodResponse, Error> {
115 let response = self
116 .client
117 .request("chainHead_v1_body", rpc_params![subscription_id, hash])
118 .await?;
119
120 Ok(response)
121 }
122
123 pub async fn chainhead_v1_header(
130 &self,
131 subscription_id: &str,
132 hash: T::Hash,
133 ) -> Result<Option<T::Header>, Error> {
134 let header: Option<Bytes> = self
136 .client
137 .request("chainHead_v1_header", rpc_params![subscription_id, hash])
138 .await?;
139
140 let header = header
141 .map(|h| codec::Decode::decode(&mut &*h.0))
142 .transpose()
143 .map_err(Error::Decode)?;
144 Ok(header)
145 }
146
147 pub async fn chainhead_v1_storage(
157 &self,
158 subscription_id: &str,
159 hash: T::Hash,
160 items: impl IntoIterator<Item = StorageQuery<&[u8]>>,
161 child_key: Option<&[u8]>,
162 ) -> Result<MethodResponse, Error> {
163 let items: Vec<StorageQuery<String>> = items
164 .into_iter()
165 .map(|item| StorageQuery {
166 key: to_hex(item.key),
167 query_type: item.query_type,
168 })
169 .collect();
170
171 let response = self
172 .client
173 .request(
174 "chainHead_v1_storage",
175 rpc_params![subscription_id, hash, items, child_key.map(to_hex)],
176 )
177 .await?;
178
179 Ok(response)
180 }
181
182 pub async fn chainhead_v1_call(
192 &self,
193 subscription_id: &str,
194 hash: T::Hash,
195 function: &str,
196 call_parameters: &[u8],
197 ) -> Result<MethodResponse, Error> {
198 let response = self
199 .client
200 .request(
201 "chainHead_v1_call",
202 rpc_params![subscription_id, hash, function, to_hex(call_parameters)],
203 )
204 .await?;
205
206 Ok(response)
207 }
208
209 pub async fn chainhead_v1_unpin(
216 &self,
217 subscription_id: &str,
218 hash: T::Hash,
219 ) -> Result<(), Error> {
220 self.client
221 .request("chainHead_v1_unpin", rpc_params![subscription_id, hash])
222 .await
223 }
224
225 pub async fn chainspec_v1_genesis_hash(&self) -> Result<T::Hash, Error> {
227 self.client
228 .request("chainSpec_v1_genesisHash", rpc_params![])
229 .await
230 }
231
232 pub async fn chainspec_v1_chain_name(&self) -> Result<String, Error> {
234 self.client
235 .request("chainSpec_v1_chainName", rpc_params![])
236 .await
237 }
238
239 pub async fn chainspec_v1_properties<Props: serde::de::DeserializeOwned>(
243 &self,
244 ) -> Result<Props, Error> {
245 self.client
246 .request("chainSpec_v1_properties", rpc_params![])
247 .await
248 }
249
250 pub async fn rpc_methods(&self) -> Result<Vec<String>, Error> {
253 self.client.request("rpc_methods", rpc_params![]).await
254 }
255
256 pub async fn transactionwatch_v1_submit_and_watch(
258 &self,
259 tx: &[u8],
260 ) -> Result<TransactionSubscription<T::Hash>, Error> {
261 let sub = self
262 .client
263 .subscribe(
264 "transactionWatch_v1_submitAndWatch",
265 rpc_params![to_hex(tx)],
266 "transactionWatch_v1_unwatch",
267 )
268 .await?;
269
270 Ok(TransactionSubscription { sub, done: false })
271 }
272
273 pub async fn transaction_v1_broadcast(&self, tx: &[u8]) -> Result<Option<String>, Error> {
279 self.client
280 .request("transaction_v1_broadcast", rpc_params![to_hex(tx)])
281 .await
282 }
283
284 pub async fn transaction_v1_stop(&self, operation_id: &str) -> Result<(), Error> {
290 self.client
291 .request("transaction_v1_stop", rpc_params![operation_id])
292 .await
293 }
294
295 pub async fn archive_v1_body(&self, block_hash: T::Hash) -> Result<Option<Vec<Bytes>>, Error> {
300 self.client
301 .request("archive_v1_body", rpc_params![block_hash])
302 .await
303 }
304
305 pub async fn archive_v1_call(
307 &self,
308 block_hash: T::Hash,
309 function: &str,
310 call_parameters: &[u8],
311 ) -> Result<ArchiveCallResult, Error> {
312 use serde::de::Error as _;
313
314 #[derive(Deserialize)]
317 struct Response {
318 success: bool,
319 value: Option<Bytes>,
320 error: Option<String>,
321 result: Option<Bytes>,
324 }
325
326 let res: Response = self
327 .client
328 .request(
329 "archive_v1_call",
330 rpc_params![block_hash, function, to_hex(call_parameters)],
331 )
332 .await?;
333
334 let value = res.value.or(res.result);
335 match (res.success, value, res.error) {
336 (true, Some(value), _) => Ok(ArchiveCallResult::Success(value)),
337 (false, _, err) => Ok(ArchiveCallResult::Error(err.unwrap_or(String::new()))),
338 (true, None, _) => {
339 let m = "archive_v1_call: 'success: true' response should have `value: 0x1234` alongside it";
340 Err(Error::Deserialization(serde_json::Error::custom(m)))
341 }
342 }
343 }
344
345 pub async fn archive_v1_finalized_height(&self) -> Result<usize, Error> {
347 self.client
348 .request("archive_v1_finalizedHeight", rpc_params![])
349 .await
350 }
351
352 pub async fn archive_v1_genesis_hash(&self) -> Result<T::Hash, Error> {
354 self.client
355 .request("archive_v1_genesisHash", rpc_params![])
356 .await
357 }
358
359 pub async fn archive_v1_hash_by_height(&self, height: usize) -> Result<Vec<T::Hash>, Error> {
364 self.client
365 .request("archive_v1_hashByHeight", rpc_params![height])
366 .await
367 }
368
369 pub async fn archive_v1_header(&self, block_hash: T::Hash) -> Result<Option<T::Header>, Error> {
371 let maybe_encoded_header: Option<Bytes> = self
372 .client
373 .request("archive_v1_header", rpc_params![block_hash])
374 .await?;
375
376 let Some(encoded_header) = maybe_encoded_header else {
377 return Ok(None);
378 };
379
380 let header =
381 <T::Header as codec::Decode>::decode(&mut &*encoded_header.0).map_err(Error::Decode)?;
382 Ok(Some(header))
383 }
384
385 pub async fn archive_v1_storage(
387 &self,
388 block_hash: T::Hash,
389 items: impl IntoIterator<Item = StorageQuery<&[u8]>>,
390 child_key: Option<&[u8]>,
391 ) -> Result<ArchiveStorageSubscription<T::Hash>, Error> {
392 let items: Vec<StorageQuery<String>> = items
393 .into_iter()
394 .map(|item| StorageQuery {
395 key: to_hex(item.key),
396 query_type: item.query_type,
397 })
398 .collect();
399
400 let sub = self
401 .client
402 .subscribe(
403 "archive_v1_storage",
404 rpc_params![block_hash, items, child_key.map(to_hex)],
405 "archive_v1_stopStorage",
406 )
407 .await?;
408
409 Ok(ArchiveStorageSubscription { sub, done: false })
410 }
411
412 pub async fn archive_unstable_body(
422 &self,
423 block_hash: T::Hash,
424 ) -> Result<Option<Vec<Bytes>>, Error> {
425 self.client
426 .request("archive_unstable_body", rpc_params![block_hash])
427 .await
428 }
429
430 pub async fn archive_unstable_call(
432 &self,
433 block_hash: T::Hash,
434 function: &str,
435 call_parameters: &[u8],
436 ) -> Result<ArchiveCallResult, Error> {
437 use serde::de::Error as _;
438
439 #[derive(Deserialize)]
442 struct Response {
443 success: bool,
444 value: Option<Bytes>,
445 error: Option<String>,
446 result: Option<Bytes>,
449 }
450
451 let res: Response = self
452 .client
453 .request(
454 "archive_unstable_call",
455 rpc_params![block_hash, function, to_hex(call_parameters)],
456 )
457 .await?;
458
459 let value = res.value.or(res.result);
460 match (res.success, value, res.error) {
461 (true, Some(value), _) => Ok(ArchiveCallResult::Success(value)),
462 (false, _, err) => Ok(ArchiveCallResult::Error(err.unwrap_or(String::new()))),
463 (true, None, _) => {
464 let m = "archive_unstable_call: 'success: true' response should have `value: 0x1234` alongside it";
465 Err(Error::Deserialization(serde_json::Error::custom(m)))
466 }
467 }
468 }
469
470 pub async fn archive_unstable_finalized_height(&self) -> Result<usize, Error> {
472 self.client
473 .request("archive_unstable_finalizedHeight", rpc_params![])
474 .await
475 }
476
477 pub async fn archive_unstable_genesis_hash(&self) -> Result<T::Hash, Error> {
479 self.client
480 .request("archive_unstable_genesisHash", rpc_params![])
481 .await
482 }
483
484 pub async fn archive_unstable_hash_by_height(
489 &self,
490 height: usize,
491 ) -> Result<Vec<T::Hash>, Error> {
492 self.client
493 .request("archive_unstable_hashByHeight", rpc_params![height])
494 .await
495 }
496
497 pub async fn archive_unstable_header(
499 &self,
500 block_hash: T::Hash,
501 ) -> Result<Option<T::Header>, Error> {
502 let maybe_encoded_header: Option<Bytes> = self
503 .client
504 .request("archive_unstable_header", rpc_params![block_hash])
505 .await?;
506
507 let Some(encoded_header) = maybe_encoded_header else {
508 return Ok(None);
509 };
510
511 let header =
512 <T::Header as codec::Decode>::decode(&mut &*encoded_header.0).map_err(Error::Decode)?;
513 Ok(Some(header))
514 }
515
516 pub async fn archive_unstable_storage(
518 &self,
519 block_hash: T::Hash,
520 items: impl IntoIterator<Item = StorageQuery<&[u8]>>,
521 child_key: Option<&[u8]>,
522 ) -> Result<ArchiveStorageSubscription<T::Hash>, Error> {
523 let items: Vec<StorageQuery<String>> = items
524 .into_iter()
525 .map(|item| StorageQuery {
526 key: to_hex(item.key),
527 query_type: item.query_type,
528 })
529 .collect();
530
531 let sub = self
532 .client
533 .subscribe(
534 "archive_unstable_storage",
535 rpc_params![block_hash, items, child_key.map(to_hex)],
536 "archive_unstable_stopStorage",
537 )
538 .await?;
539
540 Ok(ArchiveStorageSubscription { sub, done: false })
541 }
542}
543
544#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
567#[serde(rename_all = "camelCase")]
568#[serde(tag = "event")]
569pub enum FollowEvent<Hash> {
570 Initialized(Initialized<Hash>),
574 NewBlock(NewBlock<Hash>),
576 BestBlockChanged(BestBlockChanged<Hash>),
578 Finalized(Finalized<Hash>),
580 OperationBodyDone(OperationBodyDone),
582 OperationCallDone(OperationCallDone),
584 OperationStorageItems(OperationStorageItems),
586 OperationWaitingForContinue(OperationId),
589 OperationStorageDone(OperationId),
591 OperationInaccessible(OperationId),
595 OperationError(OperationError),
599 Stop,
602}
603
604#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
611#[serde(rename_all = "camelCase")]
612pub struct Initialized<Hash> {
613 pub finalized_block_hashes: Vec<Hash>,
615 pub finalized_block_runtime: Option<RuntimeEvent>,
622}
623
624impl<'de, Hash: Deserialize<'de>> Deserialize<'de> for Initialized<Hash> {
625 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
626 #[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
628 #[serde(rename_all = "camelCase")]
629 struct InitializedIR<Hash> {
630 finalized_block_hashes: Option<Vec<Hash>>,
631 finalized_block_hash: Option<Hash>,
632 finalized_block_runtime: Option<RuntimeEvent>,
633 }
634
635 let ir = InitializedIR::deserialize(deserializer)?;
636 let finalized_block_hashes = ir
637 .finalized_block_hashes
638 .or_else(|| ir.finalized_block_hash.map(|hash| vec![hash]))
639 .ok_or_else(|| serde::de::Error::custom("Missing finalized block hashes"))?;
640
641 Ok(Initialized {
642 finalized_block_hashes,
643 finalized_block_runtime: ir.finalized_block_runtime,
644 })
645 }
646}
647
648#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
651#[serde(rename_all = "camelCase")]
652#[serde(tag = "type")]
653pub enum RuntimeEvent {
654 Valid(RuntimeVersionEvent),
656 Invalid(ErrorEvent),
658}
659
660#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
666#[serde(rename_all = "camelCase")]
667pub struct RuntimeVersionEvent {
668 pub spec: RuntimeSpec,
670}
671
672#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
675#[serde(rename_all = "camelCase")]
676pub struct RuntimeSpec {
677 pub spec_name: String,
679
680 pub impl_name: String,
682
683 pub spec_version: u32,
686
687 pub impl_version: u32,
690
691 pub transaction_version: u32,
694
695 #[serde(with = "hashmap_as_tuple_list")]
703 pub apis: HashMap<String, u32>,
704}
705
706#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
708#[serde(rename_all = "camelCase")]
709pub struct ErrorEvent {
710 pub error: String,
712}
713
714#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
716#[serde(rename_all = "camelCase")]
717pub struct NewBlock<Hash> {
718 pub block_hash: Hash,
720 pub parent_block_hash: Hash,
722 pub new_runtime: Option<RuntimeEvent>,
729}
730
731#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
733#[serde(rename_all = "camelCase")]
734pub struct BestBlockChanged<Hash> {
735 pub best_block_hash: Hash,
737}
738
739#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
741#[serde(rename_all = "camelCase")]
742pub struct Finalized<Hash> {
743 pub finalized_block_hashes: Vec<Hash>,
745 pub pruned_block_hashes: Vec<Hash>,
747}
748
749#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
751#[serde(rename_all = "camelCase")]
752pub struct OperationId {
753 pub operation_id: String,
755}
756
757#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
759#[serde(rename_all = "camelCase")]
760pub struct OperationBodyDone {
761 pub operation_id: String,
763 pub value: Vec<Bytes>,
765}
766
767#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
769#[serde(rename_all = "camelCase")]
770pub struct OperationCallDone {
771 pub operation_id: String,
773 pub output: Bytes,
775}
776
777#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
779#[serde(rename_all = "camelCase")]
780pub struct OperationStorageItems {
781 pub operation_id: String,
783 pub items: VecDeque<StorageResult>,
785}
786
787#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
789#[serde(rename_all = "camelCase")]
790pub struct OperationError {
791 pub operation_id: String,
793 pub error: String,
795}
796
797#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
799#[serde(rename_all = "camelCase")]
800pub struct StorageResult {
801 pub key: Bytes,
803 #[serde(flatten)]
805 pub result: StorageResultType,
806}
807
808#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
810#[serde(rename_all = "camelCase")]
811pub enum StorageResultType {
812 Value(Bytes),
814 Hash(Bytes),
816 ClosestDescendantMerkleValue(Bytes),
818}
819
820#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
822#[serde(rename_all = "camelCase")]
823#[serde(tag = "result")]
824pub enum MethodResponse {
825 Started(MethodResponseStarted),
827 LimitReached,
829}
830
831#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
833#[serde(rename_all = "camelCase")]
834pub struct MethodResponseStarted {
835 pub operation_id: String,
837 pub discarded_items: Option<usize>,
839}
840
841#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
843#[serde(rename_all = "camelCase")]
844pub struct StorageQuery<Key> {
845 pub key: Key,
847 #[serde(rename = "type")]
849 pub query_type: StorageQueryType,
850}
851
852#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
854#[serde(rename_all = "camelCase")]
855pub enum StorageQueryType {
856 Value,
858 Hash,
860 ClosestDescendantMerkleValue,
862 DescendantsValues,
864 DescendantsHashes,
866}
867
868pub struct FollowSubscription<Hash> {
870 sub: RpcSubscription<FollowEvent<Hash>>,
871 done: bool,
872}
873
874impl<H: Hash> FollowSubscription<H> {
875 pub async fn next(&mut self) -> Option<<Self as Stream>::Item> {
877 <Self as StreamExt>::next(self).await
878 }
879 pub fn subscription_id(&self) -> Option<&str> {
881 self.sub.subscription_id()
882 }
883}
884
885impl<H: Hash> Stream for FollowSubscription<H> {
886 type Item = <RpcSubscription<FollowEvent<H>> as Stream>::Item;
887 fn poll_next(
888 mut self: std::pin::Pin<&mut Self>,
889 cx: &mut std::task::Context<'_>,
890 ) -> std::task::Poll<Option<Self::Item>> {
891 if self.done {
892 return Poll::Ready(None);
893 }
894
895 let res = self.sub.poll_next_unpin(cx);
896
897 if let Poll::Ready(Some(Ok(FollowEvent::Stop))) = &res {
898 self.done = true;
900 }
901
902 res
903 }
904}
905
906pub struct TransactionSubscription<Hash> {
909 sub: RpcSubscription<TransactionStatus<Hash>>,
910 done: bool,
911}
912
913impl<H: Hash> TransactionSubscription<H> {
914 pub async fn next(&mut self) -> Option<<Self as Stream>::Item> {
916 <Self as StreamExt>::next(self).await
917 }
918}
919
920impl<H: Hash> Stream for TransactionSubscription<H> {
921 type Item = <RpcSubscription<TransactionStatus<H>> as Stream>::Item;
922 fn poll_next(
923 mut self: std::pin::Pin<&mut Self>,
924 cx: &mut std::task::Context<'_>,
925 ) -> std::task::Poll<Option<Self::Item>> {
926 if self.done {
927 return Poll::Ready(None);
928 }
929
930 let res = self.sub.poll_next_unpin(cx);
931
932 if let Poll::Ready(Some(Ok(res))) = &res {
933 if matches!(
934 res,
935 TransactionStatus::Dropped { .. }
936 | TransactionStatus::Error { .. }
937 | TransactionStatus::Invalid { .. }
938 | TransactionStatus::Finalized { .. }
939 ) {
940 self.done = true
942 }
943 }
944
945 res
946 }
947}
948
949#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
951#[serde(rename_all = "camelCase")]
952#[serde(tag = "event")]
953pub enum TransactionStatus<Hash> {
954 Validated,
956 Broadcasted,
962 BestChainBlockIncluded {
966 block: Option<TransactionBlockDetails<Hash>>,
968 },
969 Finalized {
971 block: TransactionBlockDetails<Hash>,
973 },
974 Error {
976 error: String,
978 },
979 Invalid {
981 error: String,
983 },
984 Dropped {
986 error: String,
988 },
989}
990
991#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
993pub struct TransactionBlockDetails<Hash> {
994 pub hash: Hash,
996 #[serde(with = "unsigned_number_as_string")]
998 pub index: u64,
999}
1000
1001#[derive(Debug, Clone, PartialEq, Eq)]
1003pub enum ArchiveCallResult {
1004 Success(Bytes),
1006 Error(String),
1008}
1009
1010impl ArchiveCallResult {
1011 pub fn as_success(self) -> Option<Bytes> {
1013 match self {
1014 ArchiveCallResult::Success(bytes) => Some(bytes),
1015 _ => None,
1016 }
1017 }
1018
1019 pub fn as_error(self) -> Option<String> {
1021 match self {
1022 ArchiveCallResult::Success(_) => None,
1023 ArchiveCallResult::Error(e) => Some(e),
1024 }
1025 }
1026}
1027
1028pub struct ArchiveStorageSubscription<Hash> {
1030 sub: RpcSubscription<ArchiveStorageEvent<Hash>>,
1031 done: bool,
1032}
1033
1034impl<H: Hash> ArchiveStorageSubscription<H> {
1035 pub async fn next(&mut self) -> Option<<Self as Stream>::Item> {
1037 <Self as StreamExt>::next(self).await
1038 }
1039 pub fn subscription_id(&self) -> Option<&str> {
1041 self.sub.subscription_id()
1042 }
1043}
1044
1045impl<H: Hash> Stream for ArchiveStorageSubscription<H> {
1046 type Item = <RpcSubscription<ArchiveStorageEvent<H>> as Stream>::Item;
1047 fn poll_next(
1048 mut self: std::pin::Pin<&mut Self>,
1049 cx: &mut std::task::Context<'_>,
1050 ) -> std::task::Poll<Option<Self::Item>> {
1051 if self.done {
1052 return Poll::Ready(None);
1053 }
1054
1055 let res = self.sub.poll_next_unpin(cx);
1056
1057 if let Poll::Ready(Some(Ok(ArchiveStorageEvent::Done | ArchiveStorageEvent::Error(..)))) =
1058 &res
1059 {
1060 self.done = true;
1062 }
1063
1064 res
1065 }
1066}
1067
1068#[derive(Debug, Deserialize)]
1070#[serde(tag = "event")]
1071pub enum ArchiveStorageEvent<Hash> {
1072 #[serde(rename = "storage")]
1074 Item(ArchiveStorageEventItem<Hash>),
1075 #[serde(rename = "storageError")]
1078 Error(ArchiveStorageEventError),
1079 #[serde(rename = "storageDone")]
1081 Done,
1082}
1083
1084impl<Hash> ArchiveStorageEvent<Hash> {
1085 pub fn as_item(self) -> Option<ArchiveStorageEventItem<Hash>> {
1087 match self {
1088 ArchiveStorageEvent::Item(item) => Some(item),
1089 _ => None,
1090 }
1091 }
1092
1093 pub fn as_error(self) -> Option<ArchiveStorageEventError> {
1095 match self {
1096 ArchiveStorageEvent::Error(e) => Some(e),
1097 _ => None,
1098 }
1099 }
1100
1101 pub fn is_done(self) -> bool {
1103 matches!(self, ArchiveStorageEvent::Done)
1104 }
1105}
1106
1107#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
1109#[serde(rename_all = "camelCase")]
1110pub struct ArchiveStorageEventError {
1111 pub error: String,
1113}
1114
1115#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
1117#[serde(rename_all = "camelCase")]
1118pub struct ArchiveStorageEventItem<Hash> {
1119 pub key: Bytes,
1121 pub value: Option<Bytes>,
1124 pub hash: Option<Hash>,
1127 pub closest_descendant_merkle_value: Option<Bytes>,
1130 pub child_trie_key: Option<Bytes>,
1133}
1134
1135#[derive(PartialEq, Eq, Clone, Serialize, Deserialize, Hash, PartialOrd, Ord, Debug)]
1137pub struct Bytes(#[serde(with = "impl_serde::serialize")] pub Vec<u8>);
1138impl std::ops::Deref for Bytes {
1139 type Target = [u8];
1140 fn deref(&self) -> &[u8] {
1141 &self.0[..]
1142 }
1143}
1144impl From<Vec<u8>> for Bytes {
1145 fn from(s: Vec<u8>) -> Self {
1146 Bytes(s)
1147 }
1148}
1149
1150fn to_hex(bytes: impl AsRef<[u8]>) -> String {
1151 format!("0x{}", hex::encode(bytes.as_ref()))
1152}
1153
1154pub(crate) mod unsigned_number_as_string {
1157 use serde::de::{Deserializer, Visitor};
1158 use std::fmt;
1159
1160 pub fn deserialize<'de, N: From<u64>, D>(deserializer: D) -> Result<N, D::Error>
1162 where
1163 D: Deserializer<'de>,
1164 {
1165 deserializer.deserialize_any(NumberVisitor(std::marker::PhantomData))
1166 }
1167
1168 struct NumberVisitor<N>(std::marker::PhantomData<N>);
1169
1170 impl<N: From<u64>> Visitor<'_> for NumberVisitor<N> {
1171 type Value = N;
1172
1173 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1174 formatter.write_str("an unsigned integer or a string containing one")
1175 }
1176
1177 fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
1178 let n: u64 = v.parse().map_err(serde::de::Error::custom)?;
1179 Ok(n.into())
1180 }
1181
1182 fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
1183 Ok(v.into())
1184 }
1185 }
1186
1187 use serde::ser::Serializer;
1188
1189 pub fn serialize<S>(item: &u64, serializer: S) -> Result<S::Ok, S::Error>
1191 where
1192 S: Serializer,
1193 {
1194 serializer.serialize_str(&item.to_string())
1195 }
1196}
1197
1198pub(crate) mod hashmap_as_tuple_list {
1214 use serde::de::{Deserialize, Deserializer, SeqAccess, Visitor};
1215 use std::collections::HashMap;
1216 use std::fmt;
1217 use std::hash::{BuildHasher, Hash};
1218 use std::marker::PhantomData;
1219
1220 pub fn deserialize<'de, K, V, BH, D>(deserializer: D) -> Result<HashMap<K, V, BH>, D::Error>
1222 where
1223 D: Deserializer<'de>,
1224 K: Eq + Hash + Deserialize<'de>,
1225 V: Deserialize<'de>,
1226 BH: BuildHasher + Default,
1227 {
1228 deserializer.deserialize_any(HashMapVisitor(PhantomData))
1229 }
1230
1231 #[allow(clippy::type_complexity)]
1232 struct HashMapVisitor<K, V, BH>(PhantomData<fn() -> HashMap<K, V, BH>>);
1233
1234 impl<'de, K, V, BH> Visitor<'de> for HashMapVisitor<K, V, BH>
1235 where
1236 K: Deserialize<'de> + Eq + Hash,
1237 V: Deserialize<'de>,
1238 BH: BuildHasher + Default,
1239 {
1240 type Value = HashMap<K, V, BH>;
1241
1242 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1243 formatter.write_str("a list of key-value pairs")
1244 }
1245
1246 fn visit_map<A>(self, mut m: A) -> Result<Self::Value, A::Error>
1248 where
1249 A: serde::de::MapAccess<'de>,
1250 {
1251 let mut map =
1252 HashMap::with_capacity_and_hasher(m.size_hint().unwrap_or(0), BH::default());
1253 while let Some((key, value)) = m.next_entry()? {
1254 map.insert(key, value);
1255 }
1256 Ok(map)
1257 }
1258
1259 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
1261 where
1262 A: SeqAccess<'de>,
1263 {
1264 let mut map =
1265 HashMap::with_capacity_and_hasher(seq.size_hint().unwrap_or(0), BH::default());
1266 while let Some((key, value)) = seq.next_element()? {
1267 map.insert(key, value);
1268 }
1269 Ok(map)
1270 }
1271 }
1272
1273 use serde::ser::{Serialize, SerializeSeq, Serializer};
1274
1275 pub fn serialize<S, K: Eq + Hash + Serialize, V: Serialize>(
1277 item: &HashMap<K, V>,
1278 serializer: S,
1279 ) -> Result<S::Ok, S::Error>
1280 where
1281 S: Serializer,
1282 {
1283 let mut seq = serializer.serialize_seq(None)?;
1284 for i in item {
1285 seq.serialize_element(&i)?;
1286 }
1287 seq.end()
1288 }
1289}
1290
1291#[cfg(test)]
1292mod test {
1293 use super::*;
1294
1295 #[test]
1296 fn can_deserialize_apis_from_tuple_or_object() {
1297 let old_response = serde_json::json!({
1298 "authoringVersion": 10,
1299 "specName": "westend",
1300 "implName": "parity-westend",
1301 "specVersion": 9122,
1302 "implVersion": 0,
1303 "stateVersion": 1,
1304 "transactionVersion": 7,
1305 "apis": [
1306 ["0xdf6acb689907609b", 3],
1307 ["0x37e397fc7c91f5e4", 1],
1308 ["0x40fe3ad401f8959a", 5],
1309 ["0xd2bc9897eed08f15", 3],
1310 ["0xf78b278be53f454c", 2],
1311 ["0xaf2c0297a23e6d3d", 1],
1312 ["0x49eaaf1b548a0cb0", 1],
1313 ["0x91d5df18b0d2cf58", 1],
1314 ["0xed99c5acb25eedf5", 3],
1315 ["0xcbca25e39f142387", 2],
1316 ["0x687ad44ad37f03c2", 1],
1317 ["0xab3c0572291feb8b", 1],
1318 ["0xbc9d89904f5b923f", 1],
1319 ["0x37c8bb1350a9a2a8", 1]
1320 ]
1321 });
1322 let old_spec: RuntimeSpec = serde_json::from_value(old_response).unwrap();
1323
1324 let new_response = serde_json::json!({
1325 "specName": "westend",
1326 "implName": "parity-westend",
1327 "specVersion": 9122,
1328 "implVersion": 0,
1329 "transactionVersion": 7,
1330 "apis": {
1331 "0xdf6acb689907609b": 3,
1332 "0x37e397fc7c91f5e4": 1,
1333 "0x40fe3ad401f8959a": 5,
1334 "0xd2bc9897eed08f15": 3,
1335 "0xf78b278be53f454c": 2,
1336 "0xaf2c0297a23e6d3d": 1,
1337 "0x49eaaf1b548a0cb0": 1,
1338 "0x91d5df18b0d2cf58": 1,
1339 "0xed99c5acb25eedf5": 3,
1340 "0xcbca25e39f142387": 2,
1341 "0x687ad44ad37f03c2": 1,
1342 "0xab3c0572291feb8b": 1,
1343 "0xbc9d89904f5b923f": 1,
1344 "0x37c8bb1350a9a2a8": 1
1345 }
1346 });
1347 let new_spec: RuntimeSpec = serde_json::from_value(new_response).unwrap();
1348
1349 assert_eq!(old_spec, new_spec);
1350 }
1351
1352 #[test]
1353 fn can_deserialize_from_number_or_string() {
1354 #[derive(Debug, Deserialize)]
1355 struct Foo64 {
1356 #[serde(with = "super::unsigned_number_as_string")]
1357 num: u64,
1358 }
1359 #[derive(Debug, Deserialize)]
1360 struct Foo32 {
1361 #[serde(with = "super::unsigned_number_as_string")]
1362 num: u128,
1363 }
1364
1365 let from_string = serde_json::json!({
1366 "num": "123"
1367 });
1368 let from_num = serde_json::json!({
1369 "num": 123
1370 });
1371 let from_err = serde_json::json!({
1372 "num": "123a"
1373 });
1374
1375 let f1: Foo64 =
1376 serde_json::from_value(from_string.clone()).expect("can deser string into u64");
1377 let f2: Foo32 = serde_json::from_value(from_string).expect("can deser string into u32");
1378 let f3: Foo64 = serde_json::from_value(from_num.clone()).expect("can deser num into u64");
1379 let f4: Foo32 = serde_json::from_value(from_num).expect("can deser num into u32");
1380
1381 assert_eq!(f1.num, 123);
1382 assert_eq!(f2.num, 123);
1383 assert_eq!(f3.num, 123);
1384 assert_eq!(f4.num, 123);
1385
1386 let _ = serde_json::from_value::<Foo32>(from_err)
1388 .expect_err("can't deser invalid num into u32");
1389 }
1390
1391 #[test]
1392 fn chain_head_initialized() {
1393 let event = serde_json::json!({
1395 "finalizedBlockHashes": ["0x1", "0x2"],
1396 });
1397 let decoded: Initialized<String> = serde_json::from_value(event).unwrap();
1398 assert_eq!(
1399 decoded.finalized_block_hashes,
1400 vec!["0x1".to_string(), "0x2".to_string()]
1401 );
1402
1403 let event = serde_json::json!({
1405 "finalizedBlockHash": "0x1",
1406 });
1407 let decoded: Initialized<String> = serde_json::from_value(event).unwrap();
1408 assert_eq!(decoded.finalized_block_hashes, vec!["0x1".to_string()]);
1409
1410 let event = serde_json::json!({
1412 "finalizedBlockHash": ["0x1"],
1413 });
1414 let _ = serde_json::from_value::<Initialized<String>>(event).unwrap_err();
1415 }
1416}