evm_selectors/download.rs
1use crate::EvmSelectors;
2use anyhow::Result;
3use reqwest::Client;
4use std::{fs, path::Path, time::Duration};
5
6impl EvmSelectors {
7 /// Downloads the latest known selectors from the [OpenChain API].
8 /// The result is returned as string and not persisted.
9 /// Note that the download speed can differ significantly, from seconds to an hour or more.
10 /// A timeout can be specified to limit the time the request is allowed to take.
11 ///
12 /// # Errors
13 ///
14 /// This function will return an error if the HTTP request fails.
15 ///
16 /// [OpenChain API]: https://docs.openchain.xyz/
17 pub async fn download(timeout: Option<Duration>) -> Result<String> {
18 let url = "https://api.openchain.xyz/signature-database/v1/export";
19 let client = Client::new();
20 let mut request = client.get(url);
21 if let Some(timeout) = timeout {
22 request = request.timeout(timeout);
23 }
24
25 let response = request.send().await?;
26
27 if !response.status().is_success() {
28 return Err(anyhow::anyhow!(
29 "Failed to download from {}: Request returned bad status code {}",
30 url,
31 response.status()
32 ));
33 }
34
35 Ok(response.text().await?)
36 }
37
38 /// Downloads the latest known selectors from the [OpenChain API] and persists them to the file at `path`.
39 /// If the file exists, it will be overwritten. The directory structure will be created if it does not exist.
40 /// Note that the download speed can differ significantly, from seconds to an hour or more.
41 /// A timeout can be specified to limit the time the request is allowed to take.
42 ///
43 /// # Errors
44 ///
45 /// This function will return an error if the HTTP request fails, or if writing to the file fails.
46 ///
47 /// [OpenChain API]: https://docs.openchain.xyz/
48 pub async fn download_to_file(path: &Path, timeout: Option<Duration>) -> Result<()> {
49 let raw = Self::download(timeout).await?;
50 if let Some(parent) = path.parent() {
51 fs::create_dir_all(parent)?;
52 }
53 fs::write(path, raw)?;
54 Ok(())
55 }
56}