ens_rest_client/
lib.rs

1use ethereum_types::H160;
2use serde::{Deserialize, Serialize};
3use std::collections::BTreeMap as Map;
4use std::time::Duration;
5use thiserror::Error;
6
7#[derive(Error, Debug)]
8pub enum EnsApiError {
9    #[error("request error {0}")]
10    RequestError(String),
11    #[error("response parsing error {0}")]
12    ParseError(String),
13    #[error("server API error {0}")]
14    ApiError(String),
15    #[error("unknown client error")]
16    Unknown,
17}
18
19#[derive(Debug, Clone, Deserialize)]
20struct ReverseSingleResponse {
21    pub address: H160,
22    pub name: String,
23}
24
25#[derive(Debug, Clone, Serialize)]
26struct ReverseBulkRequest {
27    pub addresses: Vec<H160>,
28}
29
30#[derive(Debug, Clone, Deserialize)]
31struct ReverseBulkResponse {
32    pub result: Map<H160, String>,
33}
34
35#[derive(Debug, Clone, Deserialize)]
36struct ErrorResponse {
37    pub error: String,
38}
39
40pub struct Client {
41    address: String,
42}
43
44impl Client {
45    pub fn default() -> Self {
46        Self {
47            address: "https://enormous.cloud/ens/reverse/".to_owned(),
48        }
49    }
50    pub fn new(address: &str) -> Self {
51        Self {
52            address: address.to_string(),
53        }
54    }
55
56    pub fn reverse(&self, address: &H160) -> Result<String, EnsApiError> {
57        let agent = ureq::AgentBuilder::new()
58            .timeout_read(Duration::from_secs(60))
59            .timeout_write(Duration::from_secs(5))
60            .build();
61        let url = format!("{}?address={}", &self.address, address);
62        println!("ENS-API-CLIENT URL={}", url);
63        let rq = agent.get(&url).set("Content-Type", "application/json");
64        let response: String = match rq.call() {
65            Ok(x) => x.into_string().unwrap(),
66            Err(e) => return Err(EnsApiError::RequestError(e.to_string())),
67        };
68        println!("ENS-API-CLIENT response={}", response);
69        if let Ok(err) = serde_json::from_str::<ErrorResponse>(&response) {
70            return Err(EnsApiError::ApiError(err.error));
71        };
72        let res = match serde_json::from_str::<ReverseSingleResponse>(&response) {
73            Ok(x) => x.name,
74            Err(e) => return Err(EnsApiError::ParseError(e.to_string())),
75        };
76        Ok(res)
77    }
78
79    pub fn bulk_reverse(&self, addresses: Vec<H160>) -> Result<Map<H160, String>, EnsApiError> {
80        let agent = ureq::AgentBuilder::new()
81            .timeout_read(Duration::from_secs(60))
82            .timeout_write(Duration::from_secs(5))
83            .build();
84
85        let payload = serde_json::to_string(&ReverseBulkRequest { addresses }).unwrap();
86        println!("ENS-API-CLIENT URL={} PAYLOAD={}", self.address, payload);
87        let rq = agent
88            .post(&self.address)
89            .set("Content-Type", "application/json");
90        let response: String = match rq.call() {
91            Ok(x) => x.into_string().unwrap(),
92            Err(e) => return Err(EnsApiError::RequestError(e.to_string())),
93        };
94        println!("ENS-API-CLIENT response={}", response);
95        if let Ok(err) = serde_json::from_str::<ErrorResponse>(&response) {
96            return Err(EnsApiError::ApiError(err.error));
97        };
98        let res = match serde_json::from_str::<ReverseBulkResponse>(&response) {
99            Ok(x) => x.result,
100            Err(e) => return Err(EnsApiError::ParseError(e.to_string())),
101        };
102        Ok(res)
103    }
104}