moonbeam_service/lazy_loading/
frontier_backend.rs1use fc_api::{LogIndexerBackend, TransactionMetadata};
24use serde::de::DeserializeOwned;
25use sp_core::H256;
26use sp_runtime::traits::{Block as BlockT, Header};
27use std::sync::Arc;
28
29#[derive(Clone)]
35pub struct LazyLoadingFrontierBackend<Block: BlockT> {
36 pub(crate) rpc_client: Arc<super::rpc_client::RPC>,
37 pub(crate) frontier_backend: Arc<dyn fc_api::Backend<Block> + Send + Sync>,
38}
39
40impl<Block: BlockT + DeserializeOwned> LazyLoadingFrontierBackend<Block>
41where
42 <Block::Header as Header>::Number: From<u32>,
43{
44 fn get_substrate_block_hash(
45 &self,
46 block_number: <Block::Header as Header>::Number,
47 ) -> Result<Option<Block::Hash>, String> {
48 self.rpc_client
49 .block_hash::<Block>(Some(block_number))
50 .map_err(|e| format!("failed to get substrate block hash: {:?}", e))
51 }
52}
53
54#[async_trait::async_trait]
55impl<Block: BlockT + DeserializeOwned> fc_api::Backend<Block> for LazyLoadingFrontierBackend<Block>
56where
57 <Block::Header as Header>::Number: From<u32>,
58{
59 async fn block_hash(&self, eth_block_hash: &H256) -> Result<Option<Vec<Block::Hash>>, String> {
60 let block = self
61 .rpc_client
62 .block_by_hash(eth_block_hash, false)
63 .map_err(|e| format!("failed to get block by hash: {:?}", e))?;
64
65 match block {
66 Some(block) => {
67 let block_number = block.header.number.as_u32().into();
68 let substrate_block_hash = self.get_substrate_block_hash(block_number)?;
69 Ok(substrate_block_hash.map(|h| vec![h]))
70 }
71 None => Ok(None),
72 }
73 }
74
75 async fn transaction_metadata(
76 &self,
77 eth_transaction_hash: &H256,
78 ) -> Result<Vec<TransactionMetadata<Block>>, String> {
79 let transaction = self
80 .rpc_client
81 .transaction_by_hash(eth_transaction_hash)
82 .map_err(|e| format!("failed to get transaction by hash: {:?}", e))?;
83
84 match transaction {
85 Some(tx) => {
86 let block_number = tx.block_number.unwrap_or_default().as_u32().into();
87 let substrate_block_hash = self.get_substrate_block_hash(block_number)?;
88
89 Ok(vec![TransactionMetadata::<Block> {
90 ethereum_index: tx.transaction_index.unwrap_or_default().as_u32(),
91 ethereum_block_hash: tx.block_hash.unwrap_or_default(),
92 substrate_block_hash: substrate_block_hash.unwrap_or_default(),
93 }])
94 }
95 None => Ok(vec![]),
96 }
97 }
98
99 fn log_indexer(&self) -> &dyn LogIndexerBackend<Block> {
100 self.frontier_backend.log_indexer()
101 }
102
103 async fn first_block_hash(&self) -> Result<Block::Hash, String> {
104 self.frontier_backend.first_block_hash().await
105 }
106
107 async fn latest_block_hash(&self) -> Result<Block::Hash, String> {
108 self.frontier_backend.latest_block_hash().await
109 }
110}