forked from jl777/SuperNET
-
Notifications
You must be signed in to change notification settings - Fork 84
/
tendermint_wasm_rpc.rs
125 lines (110 loc) · 3.87 KB
/
tendermint_wasm_rpc.rs
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
117
118
119
120
121
122
123
124
125
use common::APPLICATION_JSON;
use cosmrs::tendermint::block::Height;
use derive_more::Display;
use http::header::{ACCEPT, CONTENT_TYPE};
use http::uri::InvalidUri;
use http::{StatusCode, Uri};
use mm2_net::transport::SlurpError;
use mm2_net::wasm::http::FetchRequest;
use std::str::FromStr;
use tendermint_rpc::endpoint::{abci_info, broadcast};
pub use tendermint_rpc::endpoint::{abci_query::{AbciQuery, Request as AbciRequest},
health::Request as HealthRequest,
tx_search::Request as TxSearchRequest};
use tendermint_rpc::error::Error as TendermintRpcError;
pub use tendermint_rpc::query::Query as TendermintQuery;
use tendermint_rpc::request::SimpleRequest;
pub use tendermint_rpc::Order;
use tendermint_rpc::Response;
#[derive(Debug, Clone)]
pub struct HttpClient {
uri: String,
}
#[derive(Debug, Display)]
pub(crate) enum HttpClientInitError {
InvalidUri(InvalidUri),
}
impl From<InvalidUri> for HttpClientInitError {
fn from(err: InvalidUri) -> Self { HttpClientInitError::InvalidUri(err) }
}
#[derive(Debug, Display)]
pub enum PerformError {
TendermintRpc(TendermintRpcError),
Slurp(SlurpError),
#[display(fmt = "Request failed with status code {}, response {}", status_code, response)]
StatusCode {
status_code: StatusCode,
response: String,
},
}
impl From<SlurpError> for PerformError {
fn from(err: SlurpError) -> Self { PerformError::Slurp(err) }
}
impl From<TendermintRpcError> for PerformError {
fn from(err: TendermintRpcError) -> Self { PerformError::TendermintRpc(err) }
}
impl HttpClient {
pub(crate) fn new(url: &str) -> Result<Self, HttpClientInitError> {
Uri::from_str(url)?;
Ok(HttpClient { uri: url.to_owned() })
}
#[inline]
pub fn uri(&self) -> http::Uri { Uri::from_str(&self.uri).expect("This should never happen.") }
pub(crate) async fn perform<R>(&self, request: R) -> Result<R::Output, PerformError>
where
R: SimpleRequest,
{
let request_str = request.into_json();
let (status_code, response_str) = FetchRequest::post(&self.uri)
.cors()
.body_utf8(request_str)
.header(ACCEPT.as_str(), APPLICATION_JSON)
.header(CONTENT_TYPE.as_str(), APPLICATION_JSON)
.request_str()
.await
.map_err(|e| e.into_inner())?;
if !status_code.is_success() {
return Err(PerformError::StatusCode {
status_code,
response: response_str,
});
}
Ok(R::Response::from_string(response_str)?.into())
}
/// `/abci_info`: get information about the ABCI application.
pub async fn abci_info(&self) -> Result<abci_info::Response, PerformError> {
// FIXME: This should be a breaking change.
self.perform(abci_info::Request).await
}
/// `/abci_query`: query the ABCI application
pub async fn abci_query<V>(
&self,
path: Option<String>,
data: V,
height: Option<Height>,
prove: bool,
) -> Result<AbciQuery, PerformError>
where
V: Into<Vec<u8>> + Send,
{
Ok(self
.perform(AbciRequest::new(path, data, height, prove))
.await?
.response)
}
/// `/broadcast_tx_commit`: broadcast a transaction, returning the response
/// from `DeliverTx`.
pub async fn broadcast_tx_commit(&self, tx: Vec<u8>) -> Result<broadcast::tx_commit::Response, PerformError> {
self.perform(broadcast::tx_commit::Request::new(tx)).await
}
}
mod tests {
use super::*;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
async fn test_get_abci_info() {
let client = HttpClient::new("https://rpc.sentry-02.theta-testnet.polypore.xyz").unwrap();
client.abci_info().await.unwrap();
}
}