1use crate::types::{
2 AccountBalanceRequest, AccountBalanceResponse, AccountCoinsRequest, AccountCoinsResponse,
3 AccountFaucetRequest, BlockRequest, BlockResponse, BlockTransactionRequest,
4 BlockTransactionResponse, ConstructionCombineRequest, ConstructionCombineResponse,
5 ConstructionDeriveRequest, ConstructionDeriveResponse, ConstructionHashRequest,
6 ConstructionMetadataRequest, ConstructionMetadataResponse, ConstructionParseRequest,
7 ConstructionParseResponse, ConstructionPayloadsRequest, ConstructionPayloadsResponse,
8 ConstructionPreprocessRequest, ConstructionPreprocessResponse, ConstructionSubmitRequest,
9 EventsBlocksRequest, EventsBlocksResponse, MempoolResponse, MempoolTransactionRequest,
10 MempoolTransactionResponse, MetadataRequest, NetworkIdentifier, NetworkListResponse,
11 NetworkOptionsResponse, NetworkRequest, NetworkStatusResponse, SearchTransactionsRequest,
12 SearchTransactionsResponse, TransactionIdentifierResponse,
13};
14use anyhow::Result;
15use rosetta_core::types::{CallRequest, CallResponse};
16use serde::{de::DeserializeOwned, Serialize};
17
18#[derive(Clone)]
20pub struct Client {
21 http: surf::Client,
23}
24
25impl Client {
26 pub fn new(url: &str) -> Result<Self> {
28 let http = surf::Config::new().set_base_url(url.parse()?).try_into()?;
29 Ok(Self { http })
30 }
31
32 async fn post<Q: Serialize, R: DeserializeOwned>(&self, path: &str, request: &Q) -> Result<R> {
34 let mut res = self
35 .http
36 .post(path)
37 .body_json(request)
38 .map_err(|e| e.into_inner())?
39 .send()
40 .await
41 .map_err(|e| e.into_inner())?;
42 match res.status() as u16 {
43 200 => Ok(res.body_json().await.map_err(|e| e.into_inner())?),
44 404 => anyhow::bail!("unsupported endpoint {}", path),
45 500 => {
46 let error: crate::types::Error =
47 res.body_json().await.map_err(|e| e.into_inner())?;
48 log::error!("{:#?}", error);
49 Err(error.into())
50 }
51 _ => anyhow::bail!("unexpected status code {}", res.status()),
52 }
53 }
54
55 pub async fn network_list(&self) -> Result<Vec<NetworkIdentifier>> {
57 let request = MetadataRequest { metadata: None };
58 let response: NetworkListResponse = self.post("/network/list", &request).await?;
59 Ok(response.network_identifiers)
60 }
61
62 pub async fn network_options(
64 &self,
65 network_identifier: NetworkIdentifier,
66 ) -> Result<NetworkOptionsResponse> {
67 let request = NetworkRequest {
68 network_identifier,
69 metadata: None,
70 };
71 self.post("/network/options", &request).await
72 }
73
74 pub async fn network_status(
76 &self,
77 network_identifier: NetworkIdentifier,
78 ) -> Result<NetworkStatusResponse> {
79 let request = NetworkRequest {
80 network_identifier,
81 metadata: None,
82 };
83 self.post("/network/status", &request).await
84 }
85
86 pub async fn account_balance(
88 &self,
89 request: &AccountBalanceRequest,
90 ) -> Result<AccountBalanceResponse> {
91 self.post("/account/balance", &request).await
92 }
93
94 pub async fn account_coins(
96 &self,
97 request: &AccountCoinsRequest,
98 ) -> Result<AccountCoinsResponse> {
99 self.post("/account/coins", &request).await
100 }
101
102 pub async fn account_faucet(
104 &self,
105 request: &AccountFaucetRequest,
106 ) -> Result<TransactionIdentifierResponse> {
107 self.post("/account/faucet", &request).await
108 }
109
110 pub async fn block(&self, request: &BlockRequest) -> Result<BlockResponse> {
112 self.post("/block", &request).await
113 }
114
115 pub async fn block_transaction(
117 &self,
118 request: &BlockTransactionRequest,
119 ) -> Result<BlockTransactionResponse> {
120 self.post("/block/transaction", &request).await
121 }
122
123 pub async fn mempool(&self, network_identifier: NetworkIdentifier) -> Result<MempoolResponse> {
125 let request = NetworkRequest {
126 network_identifier,
127 metadata: None,
128 };
129 self.post("/mempool", &request).await
130 }
131
132 pub async fn mempool_transaction(
134 &self,
135 request: &MempoolTransactionRequest,
136 ) -> Result<MempoolTransactionResponse> {
137 self.post("/mempool/transaction", &request).await
138 }
139
140 pub async fn call(&self, request: &CallRequest) -> Result<CallResponse> {
142 self.post("/call", &request).await
143 }
144
145 pub async fn construction_combine(
147 &self,
148 request: &ConstructionCombineRequest,
149 ) -> Result<ConstructionCombineResponse> {
150 self.post("/construction/combine", &request).await
151 }
152
153 pub async fn construction_derive(
155 &self,
156 request: &ConstructionDeriveRequest,
157 ) -> Result<ConstructionDeriveResponse> {
158 self.post("/construction/derive", &request).await
159 }
160
161 pub async fn construction_hash(
163 &self,
164 request: &ConstructionHashRequest,
165 ) -> Result<TransactionIdentifierResponse> {
166 self.post("/construction/hash", &request).await
167 }
168
169 pub async fn construction_metadata(
171 &self,
172 request: &ConstructionMetadataRequest,
173 ) -> Result<ConstructionMetadataResponse> {
174 self.post("/construction/metadata", &request).await
175 }
176
177 pub async fn construction_parse(
179 &self,
180 request: &ConstructionParseRequest,
181 ) -> Result<ConstructionParseResponse> {
182 self.post("/construction/parse", &request).await
183 }
184
185 pub async fn construction_payloads(
187 &self,
188 request: &ConstructionPayloadsRequest,
189 ) -> Result<ConstructionPayloadsResponse> {
190 self.post("/construction/payloads", &request).await
191 }
192
193 pub async fn construction_preprocess(
195 &self,
196 request: &ConstructionPreprocessRequest,
197 ) -> Result<ConstructionPreprocessResponse> {
198 self.post("/construction/preprocess", &request).await
199 }
200
201 pub async fn construction_submit(
203 &self,
204 request: &ConstructionSubmitRequest,
205 ) -> Result<TransactionIdentifierResponse> {
206 self.post("/construction/submit", &request).await
207 }
208
209 pub async fn events_blocks(
211 &self,
212 request: &EventsBlocksRequest,
213 ) -> Result<EventsBlocksResponse> {
214 self.post("/events/blocks", &request).await
215 }
216
217 pub async fn search_transactions(
219 &self,
220 request: &SearchTransactionsRequest,
221 ) -> Result<SearchTransactionsResponse> {
222 self.post("/search/transactions", &request).await
223 }
224}