alchemy_api/
alchemy.rs

1use crate::cores;
2use async_trait::async_trait;
3use reqwest::{Client, Request};
4use url::Url;
5
6/// A representation of the Alchemy API.
7#[derive(Clone, Debug)]
8pub struct Alchemy {
9    /// The client to use for API calls.
10    client: Client,
11    /// The base URL to use for API calls.
12    base_url: Url,
13    /// The authentication information to use when communicating with [Alchemy API].
14    ///
15    /// Will be added as `X-Alchemy-Token` header in every requests.
16    auth: String,
17}
18
19impl Alchemy {
20    /// Create a new Alchemy instance, with X-Alchemy-Token.
21    pub fn new(auth: &str) -> Self {
22        Self {
23            client: Client::new(),
24            base_url: Url::parse("https://dashboard.alchemy.com").unwrap(),
25            auth: auth.to_string(),
26        }
27    }
28}
29
30#[async_trait]
31impl cores::client::Client for Alchemy {
32    fn endpoint(&self, endpoint: &str) -> anyhow::Result<Url> {
33        self.base_url.join(endpoint).map_err(anyhow::Error::from)
34    }
35
36    async fn send(
37        &self,
38        req: http::request::Builder,
39        body: Vec<u8>,
40    ) -> anyhow::Result<http::Response<bytes::Bytes>> {
41        let http_req = req.body(body)?;
42        let mut request: Request = http_req.try_into()?;
43        request
44            .headers_mut()
45            .insert("X-Alchemy-Token", self.auth.parse().unwrap());
46
47        let resp = self.client.execute(request).await?;
48        let mut http_resp = http::Response::builder()
49            .status(resp.status())
50            .version(resp.version());
51        let headers = http_resp.headers_mut().unwrap();
52        for (key, value) in resp.headers() {
53            headers.insert(key, value.clone());
54        }
55
56        Ok(http_resp.body(resp.bytes().await?)?)
57    }
58}