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}