phos_data_network/
builder.rs1use std::{marker::PhantomData, sync::Arc};
2#[cfg(not(target_arch = "wasm32"))]
3use std::{net::SocketAddr, path::PathBuf};
4
5use eyre::{eyre, Result};
6use reqwest::{IntoUrl, Url};
7
8use helios_core::execution::{
9 cache::CachingProvider,
10 providers::{
11 block::block_cache::BlockCache, historical::eip2935::Eip2935Provider,
12 rpc::RpcExecutionProvider, verifiable_api::VerifiableApiExecutionProvider,
13 },
14};
15
16#[cfg(not(target_arch = "wasm32"))]
17use crate::database::FileDB;
18use crate::{
19 config::{networks::Network, Config, TrustOptions},
20 consensus::ConsensusClient,
21 database::{ConfigDB, Database},
22 spec::DataNetwork,
23 DataNetworkClient,
24};
25
26pub struct DataNetworkClientBuilder<DB: Database> {
27 network: Option<Network>,
28 consensus_rpc: Option<Url>,
29 execution_rpc: Option<Url>,
30 verifiable_api: Option<Url>,
31 trust_options: Option<TrustOptions>,
32 #[cfg(not(target_arch = "wasm32"))]
33 rpc_address: Option<SocketAddr>,
34 #[cfg(not(target_arch = "wasm32"))]
35 data_dir: Option<PathBuf>,
36 config: Option<Config>,
37 phantom: PhantomData<DB>,
38}
39
40impl<DB: Database> Default for DataNetworkClientBuilder<DB> {
41 fn default() -> Self {
42 Self {
43 network: None,
44 consensus_rpc: None,
45 execution_rpc: None,
46 verifiable_api: None,
47 trust_options: None,
48 #[cfg(not(target_arch = "wasm32"))]
49 rpc_address: None,
50 #[cfg(not(target_arch = "wasm32"))]
51 data_dir: None,
52 config: None,
53 phantom: PhantomData,
54 }
55 }
56}
57
58impl<DB: Database> DataNetworkClientBuilder<DB> {
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn network(mut self, network: Network) -> Self {
64 self.network = Some(network);
65 self
66 }
67
68 pub fn consensus_rpc<T: IntoUrl>(mut self, consensus_rpc: T) -> Result<Self> {
69 self.consensus_rpc = Some(
70 consensus_rpc
71 .into_url()
72 .map_err(|_| eyre!("Invalid consensus RPC URL"))?,
73 );
74 Ok(self)
75 }
76
77 pub fn execution_rpc<T: IntoUrl>(mut self, execution_rpc: T) -> Result<Self> {
78 self.execution_rpc = Some(
79 execution_rpc
80 .into_url()
81 .map_err(|_| eyre!("Invalid execution RPC URL"))?,
82 );
83 Ok(self)
84 }
85
86 pub fn verifiable_api<T: IntoUrl>(mut self, verifiable_api: T) -> Result<Self> {
87 self.verifiable_api = Some(
88 verifiable_api
89 .into_url()
90 .map_err(|_| eyre!("Invalid verifiable API URL"))?,
91 );
92 Ok(self)
93 }
94
95 pub fn trust_options(mut self, trust_options: TrustOptions) -> Self {
96 self.trust_options = Some(trust_options);
97 self
98 }
99
100 #[cfg(not(target_arch = "wasm32"))]
101 pub fn rpc_address(mut self, rpc_address: SocketAddr) -> Self {
102 self.rpc_address = Some(rpc_address);
103 self
104 }
105
106 #[cfg(not(target_arch = "wasm32"))]
107 pub fn data_dir(mut self, data_dir: PathBuf) -> Self {
108 self.data_dir = Some(data_dir);
109 self
110 }
111
112 pub fn config(mut self, config: Config) -> Self {
113 self.config = Some(config);
114 self
115 }
116
117 pub fn build(self) -> Result<DataNetworkClient> {
118 let base_config = if let Some(network) = self.network {
119 network.to_base_config()
120 } else {
121 let config = self
122 .config
123 .as_ref()
124 .ok_or(eyre!("missing network config"))?;
125 config.to_base_config()
126 };
127
128 let consensus_rpc = self
129 .consensus_rpc
130 .or_else(|| {
131 self.config
132 .as_ref()
133 .map(|config| config.consensus_rpc.clone())
134 })
135 .or_else(|| base_config.consensus_rpc.clone())
136 .ok_or_else(|| eyre!("missing consensus rpc"))?;
137
138 let execution_rpc = self
139 .execution_rpc
140 .or_else(|| {
141 self.config
142 .as_ref()
143 .and_then(|config| config.execution_rpc.clone())
144 })
145 .or_else(|| base_config.execution_rpc.clone());
146
147 let verifiable_api = self.verifiable_api.or_else(|| {
148 self.config
149 .as_ref()
150 .and_then(|config| config.verifiable_api.clone())
151 });
152
153 let trust_options = self.trust_options.or_else(|| {
154 self.config
155 .as_ref()
156 .and_then(|config| config.trust_options.clone())
157 });
158
159 #[cfg(not(target_arch = "wasm32"))]
160 let data_dir = if self.data_dir.is_some() {
161 self.data_dir
162 } else if let Some(config) = &self.config {
163 config.data_dir.clone()
164 } else {
165 base_config.data_dir.clone()
166 };
167
168 #[cfg(not(target_arch = "wasm32"))]
169 let rpc_address = if let Some(address) = self.rpc_address {
170 Some(address)
171 } else if let Some(config) = &self.config {
172 config
173 .rpc_bind_ip
174 .zip(config.rpc_port)
175 .map(|(ip, port)| SocketAddr::new(ip, port))
176 } else {
177 Some(SocketAddr::new(
178 base_config.rpc_bind_ip,
179 base_config.rpc_port,
180 ))
181 };
182
183 let database_type = self
184 .config
185 .as_ref()
186 .and_then(|config| config.database_type.clone());
187
188 let config = Config {
189 consensus_rpc,
190 execution_rpc,
191 verifiable_api,
192 rpc_bind_ip: None,
193 rpc_port: None,
194 trust_options,
195 #[cfg(not(target_arch = "wasm32"))]
196 data_dir,
197 #[cfg(target_arch = "wasm32")]
198 data_dir: None,
199 chain: base_config.chain,
200 verifier_options: base_config.verifier_options,
201 execution_forks: base_config.execution_forks,
202 database_type,
203 };
204
205 let config = Arc::new(config);
206 let consensus = ConsensusClient::<DB>::new(config.clone())?;
207
208 if let Some(verifiable_api) = &config.verifiable_api {
209 let block_provider = BlockCache::<DataNetwork>::new();
210 let historical_provider = Eip2935Provider::new();
211 let execution = VerifiableApiExecutionProvider::with_historical_provider(
212 verifiable_api,
213 block_provider,
214 historical_provider,
215 );
216 let execution = CachingProvider::new(execution);
217
218 Ok(DataNetworkClient::new(
219 consensus,
220 execution,
221 config.execution_forks,
222 #[cfg(not(target_arch = "wasm32"))]
223 rpc_address,
224 ))
225 } else {
226 let block_provider = BlockCache::<DataNetwork>::new();
227 let rpc_url = config
228 .execution_rpc
229 .as_ref()
230 .ok_or_else(|| eyre!("missing execution rpc"))?
231 .clone();
232 let historical_provider = Eip2935Provider::new();
233 let execution = RpcExecutionProvider::with_historical_provider(
234 rpc_url,
235 block_provider,
236 historical_provider,
237 );
238 let execution = CachingProvider::new(execution);
239
240 Ok(DataNetworkClient::new(
241 consensus,
242 execution,
243 config.execution_forks,
244 #[cfg(not(target_arch = "wasm32"))]
245 rpc_address,
246 ))
247 }
248 }
249}
250
251#[cfg(not(target_arch = "wasm32"))]
252impl DataNetworkClientBuilder<FileDB> {
253 pub fn with_file_db(self) -> Self {
254 self
255 }
256}
257
258impl DataNetworkClientBuilder<ConfigDB> {
259 pub fn with_config_db(self) -> Self {
260 self
261 }
262}