gear_subxt/blocks/
block_types.rs1use crate::{
6 blocks::{extrinsic_types::ExtrinsicPartTypeIds, Extrinsics},
7 client::{OfflineClientT, OnlineClientT},
8 config::{Config, Header},
9 error::{BlockError, Error},
10 events,
11 rpc::types::ChainBlockResponse,
12 runtime_api::RuntimeApi,
13 storage::Storage,
14};
15
16use futures::lock::Mutex as AsyncMutex;
17use std::sync::Arc;
18
19pub struct Block<T: Config, C> {
21 header: T::Header,
22 client: C,
23 cached_events: CachedEvents<T>,
26}
27
28pub(crate) type CachedEvents<T> = Arc<AsyncMutex<Option<events::Events<T>>>>;
31
32impl<T, C> Block<T, C>
33where
34 T: Config,
35 C: OfflineClientT<T>,
36{
37 pub(crate) fn new(header: T::Header, client: C) -> Self {
38 Block {
39 header,
40 client,
41 cached_events: Default::default(),
42 }
43 }
44
45 pub fn hash(&self) -> T::Hash {
47 self.header.hash()
48 }
49
50 pub fn number(&self) -> <T::Header as crate::config::Header>::Number {
52 self.header().number()
53 }
54
55 pub fn header(&self) -> &T::Header {
57 &self.header
58 }
59}
60
61impl<T, C> Block<T, C>
62where
63 T: Config,
64 C: OnlineClientT<T>,
65{
66 pub async fn events(&self) -> Result<events::Events<T>, Error> {
68 get_events(&self.client, self.header.hash(), &self.cached_events).await
69 }
70
71 pub async fn body(&self) -> Result<BlockBody<T, C>, Error> {
73 let ids = ExtrinsicPartTypeIds::new(&self.client.metadata())?;
74 let block_hash = self.header.hash();
75 let Some(block_details) = self.client.rpc().block(Some(block_hash)).await? else {
76 return Err(BlockError::not_found(block_hash).into());
77 };
78
79 Ok(BlockBody::new(
80 self.client.clone(),
81 block_details,
82 self.cached_events.clone(),
83 ids,
84 ))
85 }
86
87 pub fn storage(&self) -> Storage<T, C> {
89 let block_hash = self.hash();
90 Storage::new(self.client.clone(), block_hash)
91 }
92
93 pub async fn runtime_api(&self) -> Result<RuntimeApi<T, C>, Error> {
95 Ok(RuntimeApi::new(self.client.clone(), self.hash()))
96 }
97}
98
99pub struct BlockBody<T: Config, C> {
101 details: ChainBlockResponse<T>,
102 client: C,
103 cached_events: CachedEvents<T>,
104 ids: ExtrinsicPartTypeIds,
105}
106
107impl<T, C> BlockBody<T, C>
108where
109 T: Config,
110 C: OfflineClientT<T>,
111{
112 pub(crate) fn new(
113 client: C,
114 details: ChainBlockResponse<T>,
115 cached_events: CachedEvents<T>,
116 ids: ExtrinsicPartTypeIds,
117 ) -> Self {
118 Self {
119 details,
120 client,
121 cached_events,
122 ids,
123 }
124 }
125
126 pub fn extrinsics(&self) -> Extrinsics<T, C> {
130 Extrinsics::new(
131 self.client.clone(),
132 self.details.block.extrinsics.clone(),
133 self.cached_events.clone(),
134 self.ids,
135 self.details.block.header.hash(),
136 )
137 }
138}
139
140pub(crate) async fn get_events<C, T>(
142 client: &C,
143 block_hash: T::Hash,
144 cached_events: &AsyncMutex<Option<events::Events<T>>>,
145) -> Result<events::Events<T>, Error>
146where
147 T: Config,
148 C: OnlineClientT<T>,
149{
150 let lock = cached_events.lock().await;
154 let events = match &*lock {
155 Some(events) => events.clone(),
156 None => {
157 events::EventsClient::new(client.clone())
158 .at(block_hash)
159 .await?
160 }
161 };
162
163 Ok(events)
164}