1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use derive_more::Display;
use reqwest::{Client, Method, RequestBuilder};
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value as JsonValue;
pub use error::{Error, RequestError};
pub use resources::*;
mod error;
mod resources;
pub type Response<T> = Result<T, Error>;
#[derive(Display, Debug, Clone, PartialEq, Eq)]
enum Endpoint {
#[display(fmt = "addresses")]
Addresses,
#[display(fmt = "addresses/{}", "_0")]
Address(String),
#[display(fmt = "heartbeat")]
Heartbeat,
#[display(fmt = "info")]
Info,
#[display(fmt = "keys")]
Keys,
#[display(fmt = "keys/{}", "_0")]
Key(String),
#[display(fmt = "labels")]
Labels,
#[display(fmt = "labels/{}", "_0")]
Label(String),
#[display(fmt = "networks")]
Networks,
#[display(fmt = "networks/{}", "_0")]
Network(String),
#[display(fmt = "stats")]
Stats,
#[display(fmt = "upstream")]
Upstream,
}
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Env {
#[serde(rename = "localhost")]
Localhost = 1,
#[serde(rename = "testnet")]
Testnet = 2,
#[serde(rename = "mainnet")]
#[default]
Mainnet = 3,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Blockchain {
#[serde(rename = "bitcoin")]
Bitcoin = 1,
#[serde(rename = "evm")]
Evm = 2,
}
pub struct Barreleye {
version: String,
url: String,
api_key: Option<String>,
}
impl Barreleye {
pub fn new(url: &str, api_key: Option<&str>) -> Self {
Self {
version: "v0".to_string(),
url: url.trim_end_matches('/').to_string(),
api_key: api_key.map(|v| v.to_owned()),
}
}
fn is_auth_request(&self, endpoint: Endpoint) -> bool {
endpoint != Endpoint::Info && endpoint != Endpoint::Upstream
}
async fn get<T: DeserializeOwned>(
&self,
endpoint: Endpoint,
query: &[(&str, &str)],
) -> Response<T> {
self.req::<T>(self.make(Method::GET, endpoint).query(&query)).await
}
async fn post<T: DeserializeOwned>(
&self,
method: Method,
endpoint: Endpoint,
body: JsonValue,
) -> Response<T> {
self.req::<T>(self.make(method, endpoint).json(&body)).await
}
fn make(&self, method: Method, endpoint: Endpoint) -> RequestBuilder {
let url = format!("{}/{}/{}", self.url, self.version, endpoint);
let mut req = Client::new().request(method, url);
if self.is_auth_request(endpoint) {
req = req.bearer_auth(self.api_key.clone().unwrap());
}
req
}
async fn req<T: DeserializeOwned>(&self, req: RequestBuilder) -> Response<T> {
let res = req.send().await.map_err(|_| Error::Unavailable)?;
if res.status().is_success() {
Ok(res.json::<T>().await?)
} else {
Err(Error::Barreleye(res.json::<RequestError>().await?))
}
}
}