pallet_revive_eth_rpc/
block_info_provider.rs1use crate::{
19 client::{SubscriptionType, SubstrateBlock, SubstrateBlockNumber},
20 subxt_client::SrcChainConfig,
21 ClientError,
22};
23use jsonrpsee::core::async_trait;
24use sp_core::H256;
25use std::sync::Arc;
26use subxt::{backend::legacy::LegacyRpcMethods, OnlineClient};
27use tokio::sync::RwLock;
28
29#[async_trait]
31pub trait BlockInfoProvider: Send + Sync {
32 async fn update_latest(&self, block: SubstrateBlock, subscription_type: SubscriptionType);
34
35 async fn latest_finalized_block(&self) -> Arc<SubstrateBlock>;
37
38 async fn latest_block(&self) -> Arc<SubstrateBlock>;
40
41 async fn latest_block_number(&self) -> SubstrateBlockNumber {
43 return self.latest_block().await.number()
44 }
45
46 async fn block_by_number(
48 &self,
49 block_number: SubstrateBlockNumber,
50 ) -> Result<Option<Arc<SubstrateBlock>>, ClientError>;
51
52 async fn block_by_hash(&self, hash: &H256) -> Result<Option<Arc<SubstrateBlock>>, ClientError>;
54}
55
56#[derive(Clone)]
58pub struct SubxtBlockInfoProvider {
59 latest_block: Arc<RwLock<Arc<SubstrateBlock>>>,
61
62 latest_finalized_block: Arc<RwLock<Arc<SubstrateBlock>>>,
64
65 rpc: LegacyRpcMethods<SrcChainConfig>,
67
68 api: OnlineClient<SrcChainConfig>,
70}
71
72impl SubxtBlockInfoProvider {
73 pub async fn new(
74 api: OnlineClient<SrcChainConfig>,
75 rpc: LegacyRpcMethods<SrcChainConfig>,
76 ) -> Result<Self, ClientError> {
77 let latest = Arc::new(api.blocks().at_latest().await?);
78 Ok(Self {
79 api,
80 rpc,
81 latest_block: Arc::new(RwLock::new(latest.clone())),
82 latest_finalized_block: Arc::new(RwLock::new(latest)),
83 })
84 }
85}
86
87#[async_trait]
88impl BlockInfoProvider for SubxtBlockInfoProvider {
89 async fn update_latest(&self, block: SubstrateBlock, subscription_type: SubscriptionType) {
90 let mut latest = match subscription_type {
91 SubscriptionType::FinalizedBlocks => self.latest_finalized_block.write().await,
92 SubscriptionType::BestBlocks => self.latest_block.write().await,
93 };
94 *latest = Arc::new(block);
95 }
96
97 async fn latest_block(&self) -> Arc<SubstrateBlock> {
98 self.latest_block.read().await.clone()
99 }
100
101 async fn latest_finalized_block(&self) -> Arc<SubstrateBlock> {
102 self.latest_finalized_block.read().await.clone()
103 }
104
105 async fn block_by_number(
106 &self,
107 block_number: SubstrateBlockNumber,
108 ) -> Result<Option<Arc<SubstrateBlock>>, ClientError> {
109 let latest = self.latest_block().await;
110 if block_number == latest.number() {
111 return Ok(Some(latest));
112 }
113
114 let latest_finalized = self.latest_finalized_block().await;
115 if block_number == latest_finalized.number() {
116 return Ok(Some(latest_finalized));
117 }
118
119 let Some(hash) = self.rpc.chain_get_block_hash(Some(block_number.into())).await? else {
120 return Ok(None);
121 };
122
123 match self.api.blocks().at(hash).await {
124 Ok(block) => Ok(Some(Arc::new(block))),
125 Err(subxt::Error::Block(subxt::error::BlockError::NotFound(_))) => Ok(None),
126 Err(err) => Err(err.into()),
127 }
128 }
129
130 async fn block_by_hash(&self, hash: &H256) -> Result<Option<Arc<SubstrateBlock>>, ClientError> {
131 let latest = self.latest_block().await;
132 if hash == &latest.hash() {
133 return Ok(Some(latest));
134 }
135
136 let latest_finalized = self.latest_finalized_block().await;
137 if hash == &latest_finalized.hash() {
138 return Ok(Some(latest_finalized));
139 }
140
141 match self.api.blocks().at(*hash).await {
142 Ok(block) => Ok(Some(Arc::new(block))),
143 Err(subxt::Error::Block(subxt::error::BlockError::NotFound(_))) => Ok(None),
144 Err(err) => Err(err.into()),
145 }
146 }
147}
148
149#[cfg(test)]
150pub mod test {
151 use super::*;
152 use crate::BlockInfo;
153
154 pub struct MockBlockInfoProvider;
156
157 pub struct MockBlockInfo {
158 pub number: SubstrateBlockNumber,
159 pub hash: H256,
160 }
161
162 impl BlockInfo for MockBlockInfo {
163 fn hash(&self) -> H256 {
164 self.hash
165 }
166 fn number(&self) -> SubstrateBlockNumber {
167 self.number
168 }
169 }
170
171 #[async_trait]
172 impl BlockInfoProvider for MockBlockInfoProvider {
173 async fn update_latest(
174 &self,
175 _block: SubstrateBlock,
176 _subscription_type: SubscriptionType,
177 ) {
178 }
179
180 async fn latest_finalized_block(&self) -> Arc<SubstrateBlock> {
181 unimplemented!()
182 }
183
184 async fn latest_block(&self) -> Arc<SubstrateBlock> {
185 unimplemented!()
186 }
187
188 async fn latest_block_number(&self) -> SubstrateBlockNumber {
189 2u32
190 }
191
192 async fn block_by_number(
193 &self,
194 _block_number: SubstrateBlockNumber,
195 ) -> Result<Option<Arc<SubstrateBlock>>, ClientError> {
196 Ok(None)
197 }
198
199 async fn block_by_hash(
200 &self,
201 _hash: &H256,
202 ) -> Result<Option<Arc<SubstrateBlock>>, ClientError> {
203 Ok(None)
204 }
205 }
206}