esplora_api/async_impl/client.rs
1use std::collections::HashMap;
2use reqwest;
3
4use crate::data::blockstream::{
5 AddressInfoFormat, BlockFormat, BlockStatus, MemPoolFormat, MempoolTxFormat, MerkleProofFormat,
6 OutspentFormat, TransactionFormat, TxStatusFormat, UtxoFormat,
7};
8
9/// Client to call esplora api, it use and Esplora Api Url. I can use custom reqwest Client build from reqwest client builder
10#[derive(Debug)]
11pub struct ApiClient {
12 pub url: String,
13 pub reqwest: reqwest::Client,
14}
15/// Client basics options used to custom reqwest client
16#[derive(Debug)]
17pub struct ClientOptions {
18 pub headers: Option<HeadersOptions>,
19}
20/// Headers options can be used to use authorization header
21#[derive(Debug)]
22pub struct HeadersOptions {
23 pub authorization: Option<String>,
24}
25
26impl ApiClient {
27 /// new client from endpoint Esplora Api Url, and ClientOptions.
28 ///
29 /// Example without options :
30 /// ````rust
31 /// use esplora_api::async_impl::ApiClient;
32 ///
33 /// fn main(){
34 /// let client = esplora_api::async_impl::ApiClient::new("https://some_esplora_url.com", None);
35 /// }
36 /// ````
37 /// Example with custom authorization header :
38 /// ````rust
39 /// use esplora_api::async_impl::{ApiClient, ClientOptions, HeadersOptions};
40 ///
41 /// fn main(){
42 /// let options = ClientOptions { headers: Some( HeadersOptions { authorization: Some("secret".to_string())}),};
43 /// let client = esplora_api::async_impl::ApiClient::new("https://some_esplora_url.com", Some(options));
44 /// }
45 /// ````
46 pub fn new(
47 url: &str,
48 options: Option<ClientOptions>,
49 ) -> Result<Self, Box<dyn std::error::Error>> {
50 let mut client_builder = reqwest::ClientBuilder::new();
51 // Find options
52 match options {
53 // Build headers
54 Some(ClientOptions { headers, .. }) => {
55 let mut headers_map = reqwest::header::HeaderMap::new();
56 match headers {
57 // header::AUTHORIZATION
58 Some(HeadersOptions {
59 authorization: Some(authorization),
60 }) => {
61 headers_map.insert(
62 reqwest::header::AUTHORIZATION,
63 reqwest::header::HeaderValue::from_str(&authorization).unwrap(),
64 );
65 }
66 _ => (),
67 }
68 client_builder = client_builder.default_headers(headers_map);
69 }
70 None => (),
71 }
72 let build = client_builder.build().unwrap_or(reqwest::Client::new());
73
74 Ok(ApiClient {
75 url: url.to_string(),
76 reqwest: build,
77 })
78 }
79 /// new_from_config new client from endpoint Esplora Api Url, and reqwest client.
80 ///
81 /// Example without custom reqwest client :
82 /// ````rust
83 /// use esplora_api::async_impl::ApiClient;
84 /// use reqwest;
85 /// use reqwest::header;
86 /// fn main(){
87 /// let mut headers = header::HeaderMap::new();
88 /// headers.insert(header::AUTHORIZATION,header::HeaderValue::from_static("secret"));
89 /// let reqwest_client = reqwest::Client::builder().default_headers(headers).build().unwrap();
90 /// let client = esplora_api::async_impl::ApiClient::new_from_config("https://some_esplora_url.com", reqwest_client);
91 /// }
92 /// ````
93 pub fn new_from_config(
94 url: &str,
95 client: reqwest::Client
96 )->Result<Self, Box<dyn std::error::Error>> {
97 Ok(ApiClient {
98 url: url.to_string(),
99 reqwest: client,
100 })
101 }
102 /// get_block Returns information about a block.
103 ///
104 /// Route : GET /block/:hash. Available fields:
105 ///
106 /// Elements-based chains have an additional proof field. See block format for more details.
107 /// The response from this endpoint can be cached indefinitely.
108 ///
109 /// Example :
110 /// ````rust
111 /// use esplora_api;
112 ///
113 /// #[tokio::main]
114 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
115 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
116 /// let response = client.get_block("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7").await?;
117 /// println!("{:?}",response);
118 /// Ok(())
119 /// }
120 /// ````
121 pub async fn get_block(&self, hash: &str) -> Result<BlockFormat, Box<dyn std::error::Error>> {
122 let request_url = format!("{}/block/{}", self.url, hash);
123 let resp: BlockFormat = self.reqwest.get(&request_url).send().await?.json().await?;
124 Ok(resp)
125 }
126 /// get_block_status Returns the block status.
127 ///
128 /// Route : GET /block/:hash/status. Available fields:
129 ///
130 /// Example :
131 /// ````rust
132 /// use esplora_api;
133 ///
134 /// #[tokio::main]
135 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
136 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
137 /// let response = client.get_block_status("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7").await?;
138 /// println!("{:?}",response);
139 /// Ok(())
140 /// }
141 /// ````
142 pub async fn get_block_status(
143 &self,
144 hash: &str,
145 ) -> Result<BlockStatus, Box<dyn std::error::Error>> {
146 let request_url = format!("{}{}{}{}", self.url, "/block/", hash, "/status");
147 let resp: BlockStatus = self.reqwest.get(&request_url).send().await?.json().await?;
148 Ok(resp)
149 }
150 /// get_block_txs Returns a list of transactions in the block (up to 25 transactions beginning at start_index).
151 ///
152 /// Route : GET /block/:hash/txs[/:start_index]
153 ///
154 /// Transactions returned here do not have the status field, since all the transactions share the same block and confirmation status.
155 /// The response from this endpoint can be cached indefinitely.
156 ///
157 /// Example :
158 /// ````rust
159 /// use esplora_api;
160 ///
161 /// #[tokio::main]
162 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
163 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
164 /// let response = client.get_block_txs("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7", Some(25)).await?;
165 /// println!("{:?}",response);
166 /// Ok(())
167 /// }
168 /// ````
169 pub async fn get_block_txs(
170 &self,
171 hash: &str,
172 start_index: Option<i32>, // Why Option ?
173 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
174 let request_url = if let Some(i) = start_index {
175 format!("{}/block/{}/txs/{}", self.url, hash, i)
176 } else {
177 format!("{}/block/{}/txs", self.url, hash)
178 };
179 let resp: Vec<TransactionFormat> =
180 self.reqwest.get(&request_url).send().await?.json().await?;
181 Ok(resp)
182 }
183 /// get_block_txids Returns a list of all txids in the block.
184 ///
185 /// Route : GET /block/:hash/txids
186 ///
187 ///The response from this endpoint can be cached indefinitely.
188 ///
189 /// Example :
190 /// ````rust
191 /// use esplora_api;
192 ///
193 /// #[tokio::main]
194 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
195 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
196 /// let response = client.get_block_txids("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7").await?;
197 /// println!("{:?}",response);
198 /// Ok(())
199 /// }
200 /// ````
201 pub async fn get_block_txids(
202 &self,
203 hash: &str,
204 ) -> Result<Vec<String>, Box<dyn std::error::Error>> {
205 let request_url = format!("{}{}{}{}", self.url, "/block/", hash, "/txids");
206 let resp: Vec<String> = self.reqwest.get(&request_url).send().await?.json().await?;
207 Ok(resp)
208 }
209 /// get_block_txid_at_index Returns the transaction at index :index within the specified block.
210 ///
211 /// Route : GET /block/:hash/txid/:index
212 ///
213 /// The response from this endpoint can be cached indefinitely.
214 ///
215 /// Example :
216 /// ````rust
217 /// use esplora_api;
218 ///
219 /// #[tokio::main]
220 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
221 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
222 /// let response = client.get_block_txid_at_index("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7",25).await?;
223 /// println!("{:?}",response);
224 /// Ok(())
225 /// }
226 /// ````
227 pub async fn get_block_txid_at_index(
228 &self,
229 hash: &str,
230 index: i32,
231 ) -> Result<String, Box<dyn std::error::Error>> {
232 let request_url = format!("{}/block/{}/txid/{}", self.url, hash, index);
233 let resp: String = self.reqwest.get(&request_url).send().await?.text().await?;
234 Ok(resp)
235 }
236 /// get_block_raw_format Returns the raw block representation in binary.
237 ///
238 /// Route : GET /block/:hash/raw
239 ///
240 /// The response from this endpoint can be cached indefinitely.
241 ///
242 /// Example :
243 /// ````rust
244 /// use esplora_api;
245 ///
246 /// #[tokio::main]
247 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
248 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
249 /// let response = client.get_block_raw_format("000000000000003aaa3b99e31ed1cac4744b423f9e52ada4971461c81d4192f7").await?;
250 /// println!("{:?}",response);
251 /// Ok(())
252 /// }
253 /// ````
254
255 pub async fn get_block_raw_format(
256 &self,
257 hash: &str,
258 ) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
259 let request_url = format!("{}/block/{}/raw", self.url, hash);
260 let resp = self
261 .reqwest
262 .get(&request_url)
263 .send()
264 .await?
265 .bytes()
266 .await?
267 .to_vec();
268 Ok(resp)
269 }
270
271 /// get_block_height Returns the hash of the block currently at height.
272 ///
273 /// Route : GET /block-height/:height
274 ///
275 /// Example :
276 /// ````rust
277 /// use esplora_api;
278 ///
279 /// #[tokio::main]
280 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
281 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
282 /// let response = client.get_block_height(424242).await?;
283 /// println!("{:?}",response);
284 /// Ok(())
285 /// }
286 /// ````
287 pub async fn get_block_height(
288 &self,
289 height: i32,
290 ) -> Result<String, Box<dyn std::error::Error>> {
291 let request_url = format!("{}/block-height/{}", self.url, height);
292 let resp = self.reqwest.get(&request_url).send().await?.text().await?;
293 Ok(resp)
294 }
295 /// get_blocks Returns the 10 newest blocks starting at the tip or at start_height if specified.
296 ///
297 /// Route : GET /blocks[/:start_height]
298 ///
299 /// Example :
300 /// ````rust
301 /// use esplora_api;
302 ///
303 /// #[tokio::main]
304 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
305 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
306 /// let response = client.get_blocks(1234).await?;
307 /// println!("{:?}",response);
308 /// Ok(())
309 /// }
310 /// ````
311
312 pub async fn get_blocks(
313 &self,
314 start_height: i32,
315 ) -> Result<Vec<BlockFormat>, Box<dyn std::error::Error>> {
316 let request_url = format!("{}/blocks/{}", self.url, start_height);
317 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
318 Ok(resp)
319 }
320 /// get_blocks_tip_height Returns the height of the last block.
321 ///
322 /// Route : GET /blocks/tip/height
323 ///
324 /// Example :
325 /// ````rust
326 /// use esplora_api;
327 ///
328 /// #[tokio::main]
329 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
330 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
331 /// let response = client.get_blocks_tip_height().await?;
332 /// println!("{:?}",response);
333 /// Ok(())
334 /// }
335 /// ````
336
337 pub async fn get_blocks_tip_height(&self) -> Result<i32, Box<dyn std::error::Error>> {
338 let request_url = format!("{}/blocks/tip/height", self.url);
339 let resp = self
340 .reqwest
341 .get(&request_url)
342 .send()
343 .await?
344 .text()
345 .await?
346 .parse()?;
347 Ok(resp)
348 }
349 /// get_blocks_tip_hash Returns the hash of the last block.
350 ///
351 /// Route : GET /blocks/tip/hash
352 ///
353 ///
354 ///
355 /// Example :
356 /// ````rust
357 /// use esplora_api;
358 ///
359 /// #[tokio::main]
360 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
361 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
362 /// let response = client.get_blocks_tip_height().await?;
363 /// println!("{:?}",response);
364 /// Ok(())
365 /// }
366 /// ````
367
368 pub async fn get_blocks_tip_hash(&self) -> Result<String, Box<dyn std::error::Error>> {
369 let request_url = format!("{}/blocks/tip/hash", self.url);
370 let resp = self.reqwest.get(&request_url).send().await?.text().await?;
371 Ok(resp)
372 }
373 /// get_tx Returns information about the transaction. Available fields: txid, version, locktime, size, weight, fee, vin, vout and status (see transaction format for details).
374 ///
375 /// Route : GET /tx/:txid
376 ///
377 /// Example :
378 /// ````rust
379 /// use esplora_api;
380 ///
381 /// #[tokio::main]
382 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
383 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
384 /// let response = client.get_tx("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
385 /// println!("{:?}",response);
386 /// Ok(())
387 /// }
388 /// ````
389
390 pub async fn get_tx(
391 &self,
392 txid: &str,
393 ) -> Result<TransactionFormat, Box<dyn std::error::Error>> {
394 let request_url = format!("{}/tx/{}", self.url, txid);
395 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
396 Ok(resp)
397 }
398 /// get_tx_status Returns the transaction confirmation status. Available fields: confirmed (boolean), block_height (optional) and block_hash (optional).
399 ///
400 /// Route : GET /tx/:txid/status
401 ///
402 /// Example :
403 /// ````rust
404 /// use esplora_api;
405 ///
406 /// #[tokio::main]
407 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
408 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
409 /// let response = client.get_tx_status("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
410 /// println!("{:?}",response);
411 /// Ok(())
412 /// }
413 /// ````
414 pub async fn get_tx_status(
415 &self,
416 txid: &str,
417 ) -> Result<TxStatusFormat, Box<dyn std::error::Error>> {
418 let request_url = format!("{}/tx/{}/status", self.url, txid);
419 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
420 Ok(resp)
421 }
422
423 /// get_tx_raw Returns the raw transaction as binary data.
424 ///
425 /// Route : GET /tx/:txid/raw
426 ///
427 /// Example :
428 /// ````rust
429 /// use esplora_api;
430 ///
431 /// #[tokio::main]
432 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
433 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
434 /// let response = client.get_tx_raw("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
435 /// println!("{:?}",response);
436 /// Ok(())
437 /// }
438 /// ````
439 pub async fn get_tx_raw(&self, txid: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
440 let request_url = format!("{}/tx/{}/raw", self.url, txid);
441 let resp = self
442 .reqwest
443 .get(&request_url)
444 .send()
445 .await?
446 .bytes()
447 .await?
448 .to_vec();
449 Ok(resp)
450 }
451
452 /// get_tx_hex Returns the raw transaction in hex
453 ///
454 /// Route : GET /tx/:txid/hex
455 ///
456 /// Example :
457 /// ````rust
458 /// use esplora_api;
459 ///
460 /// #[tokio::main]
461 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
462 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
463 /// let response = client.get_tx_hex("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
464 /// println!("{:?}",response);
465 /// Ok(())
466 /// }
467 /// ````
468 pub async fn get_tx_hex(&self, txid: &str) -> Result<String, Box<dyn std::error::Error>> {
469 let request_url = format!("{}/tx/{}/raw", self.url, txid);
470 let resp = self.reqwest.get(&request_url).send().await?.text().await?;
471 Ok(resp)
472 }
473 /// get_tx_merkleblock_proof Returns a merkle inclusion proof for the transaction using bitcoind's merkleblock format.
474 /// Note: This endpoint is not currently available for Liquid/Elements-based chains.
475 /// Route : GET /tx/:txid/merkleblock-proof
476 ///
477 /// Example :
478 /// ````rust
479 /// use esplora_api;
480 ///
481 /// #[tokio::main]
482 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
483 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
484 /// let response = client.get_tx_merkleblock_proof("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
485 /// println!("{:?}",response);
486 /// Ok(())
487 /// }
488 /// ````
489 pub async fn get_tx_merkleblock_proof(
490 &self,
491 txid: &str,
492 ) -> Result<String, Box<dyn std::error::Error>> {
493 let request_url = format!("{}/tx/{}/merkleblock-proof", self.url, txid);
494 let resp = self.reqwest.get(&request_url).send().await?.text().await?;
495 Ok(resp)
496 }
497
498 /// get_tx_merkle_proof Returns a merkle inclusion proof for the transaction using Electrum's blockchain.transaction.get_merkle format.
499 ///
500 /// Route : GET /tx/:txid/merkle-proof
501 ///
502 /// Example :
503 /// ````rust
504 /// use esplora_api;
505 ///
506 /// #[tokio::main]
507 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
508 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
509 /// let response = client.get_tx_merkle_proof("c9ee6eff3d73d6cb92382125c3207f6447922b545d4d4e74c47bfeb56fff7d24").await?;
510 /// println!("{:?}",response);
511 /// Ok(())
512 /// }
513 /// ````
514 pub async fn get_tx_merkle_proof(
515 &self,
516 txid: &str,
517 ) -> Result<MerkleProofFormat, Box<dyn std::error::Error>> {
518 let request_url = format!("{}/tx/{}/merkle-proof", self.url, txid);
519 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
520 Ok(resp)
521 }
522
523 /// get_tx_outspend Returns the spending status of a transaction output.
524 /// Available fields: spent (boolean), txid (optional), vin (optional) and status (optional, the status of the spending tx).
525 ///
526 /// Route : GET /tx/:txid/outspend/:vout
527 ///
528 /// Example :
529 /// ````rust
530 /// use esplora_api;
531 ///
532 /// #[tokio::main]
533 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
534 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
535 /// let response = client.get_tx_outspend("fac9af7f793330af3cc0bce4790d98499c59d47a125af7260edd61d647003316",Some(1)).await?;
536 /// println!("{:?}",response);
537 /// Ok(())
538 /// }
539 /// ````
540 pub async fn get_tx_outspend(
541 &self,
542 txid: &str,
543 vout: Option<i32>,
544 ) -> Result<OutspentFormat, Box<dyn std::error::Error>> {
545 let request_url = if let Some(vout_idx) = vout {
546 format!("{}/tx/{}/outspend/{}", self.url, txid, vout_idx)
547 } else {
548 format!("{}/tx/{}/outspend", self.url, txid) // FIXME: not sure if this exist
549 };
550 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
551 Ok(resp)
552 }
553
554 /// get_tx_outspends Returns the spending status of all transaction outputs.
555 ///
556 /// Route : GET /tx/:txid/outspends
557 ///
558 /// Example :
559 /// ````rust
560 /// use esplora_api;
561 ///
562 /// #[tokio::main]
563 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
564 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
565 /// let response = client.get_tx_outspends("fac9af7f793330af3cc0bce4790d98499c59d47a125af7260edd61d647003316").await?;
566 /// println!("{:?}",response);
567 /// Ok(())
568 /// }
569 /// ````
570
571 pub async fn get_tx_outspends(
572 &self,
573 txid: &str,
574 ) -> Result<Vec<OutspentFormat>, Box<dyn std::error::Error>> {
575 let request_url = format!("{}/tx/{}/outspends", self.url, txid);
576 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
577 Ok(resp)
578 }
579
580 /// post_tx Broadcast a raw transaction to the network.
581 /// The transaction should be provided as hex in the request body. The txid will be returned on success.
582 ///
583 /// Route : POST /tx
584 ///
585 pub async fn post_tx(
586 &self,
587 hex_transaction: &str,
588 ) -> Result<String, Box<dyn std::error::Error>> {
589 let request_url = format!("{}/tx", self.url);
590 let resp = self
591 .reqwest
592 .post(&request_url)
593 .body(hex_transaction.to_string())
594 .send()
595 .await?
596 .text()
597 .await?;
598 Ok(resp)
599 }
600
601 /// get_address Get information about an address
602 /// Available fields: address/scripthash, chain_stats and mempool_stats.
603 /// {chain,mempool}_stats each contain an object with tx_count, funded_txo_count, funded_txo_sum, spent_txo_count and spent_txo_sum.
604 /// Elements-based chains don't have the {funded,spent}_txo_sum fields.
605 ///
606 /// Route : GET /address/:address
607 ///
608 /// Example :
609 /// ````rust
610 /// use esplora_api;
611 ///
612 /// #[tokio::main]
613 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
614 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
615 /// let response = client.get_address("2MvJVm11phGoxEekPB8Hw2Tksb57eVRGHC5").await?;
616 /// println!("{:?}",response);
617 /// Ok(())
618 /// }
619 /// ````
620 pub async fn get_address(
621 &self,
622 address: &str,
623 ) -> Result<AddressInfoFormat, Box<dyn std::error::Error>> {
624 let request_url = format!("{}/address/{}", self.url, address);
625 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
626 Ok(resp)
627 }
628
629 /// get_script_hash Get information about an scripthash
630 /// Available fields: scripthash, chain_stats and mempool_stats.
631 /// {chain,mempool}_stats each contain an object with tx_count, funded_txo_count, funded_txo_sum, spent_txo_count and spent_txo_sum.
632 /// Elements-based chains don't have the {funded,spent}_txo_sum fields.
633 ///
634 /// Route : GET /scripthash/:hash
635 ///
636 /// Example :
637 /// ````rust
638 /// use esplora_api;
639 ///
640 /// #[tokio::main]
641 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
642 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
643 /// let response = client.get_script_hash("c6598a8e5728c744b9734facbf1e786c3ff5101268739d38b14ea475b60eba3c").await?;
644 /// println!("{:?}",response);
645 /// Ok(())
646 /// }
647 /// ````
648 pub async fn get_script_hash(
649 &self,
650 scripthash: &str,
651 ) -> Result<AddressInfoFormat, Box<dyn std::error::Error>> {
652 let request_url = format!("{}/scripthash/{}", self.url, scripthash);
653 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
654 Ok(resp)
655 }
656
657 /// get_address_txs Get transaction history for the specified address/scripthash, sorted with newest first.
658 /// Returns up to 50 mempool transactions plus the first 25 confirmed transactions. You can request more confirmed transactions using :last_seen_txid(see below).
659 ///
660 /// Route : GET /address/:address/txs
661 ///
662 /// Example :
663 /// ````rust
664 /// use esplora_api;
665 ///
666 /// #[tokio::main]
667 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
668 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
669 /// let response = client.get_address_txs("2MvJVm11phGoxEekPB8Hw2Tksb57eVRGHC5").await?;
670 /// println!("{:?}",response);
671 /// Ok(())
672 /// }
673 /// ````
674 pub async fn get_address_txs(
675 &self,
676 address: &str,
677 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
678 let request_url = format!("{}/address/{}/txs", self.url, address);
679 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
680 Ok(resp)
681 }
682 /// get_script_hash_txs Get transaction history for the specified address/scripthash, sorted with newest first.
683 /// Returns up to 50 mempool transactions plus the first 25 confirmed transactions. You can request more confirmed transactions using :last_seen_txid(see below).
684 ///
685 /// Route : GET /scripthash/:hash/txs
686 ///
687 /// Example :
688 /// ````rust
689 /// use esplora_api;
690 ///
691 /// #[tokio::main]
692 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
693 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
694 /// let response = client.get_script_hash_txs("c6598a8e5728c744b9734facbf1e786c3ff5101268739d38b14ea475b60eba3c").await?;
695 /// println!("{:?}",response);
696 /// Ok(())
697 /// }
698 /// ````
699
700 pub async fn get_script_hash_txs(
701 &self,
702 scripthash: &str,
703 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
704 let request_url = format!("{}/scripthash/{}/txs", self.url, scripthash);
705 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
706 Ok(resp)
707 }
708
709 /// get_address_txs_chain Get confirmed transaction history for the specified address/scripthash, sorted with newest first.
710 /// Returns 25 transactions per page. More can be requested by specifying the last txid seen by the previous query.
711 ///
712 /// Route : GET /address/:address/txs/chain[/:last_seen_txid]
713 ///
714 /// Example :
715 /// ````rust
716 /// use esplora_api;
717 ///
718 /// #[tokio::main]
719 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
720 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
721 /// let response = client.get_address_txs_chain("n1vgV8XmoggmRXzW3hGD8ZNTAgvhcwT4Gk",Some("d0075b62f8b3e464472b8edecf56083ca3e9e8424f5f332ed2f9045d7fcccddc")).await?;
722 /// println!("{:?}",response);
723 /// Ok(())
724 /// }
725 /// ````
726 pub async fn get_address_txs_chain(
727 &self,
728 address: &str,
729 txid: Option<&str>,
730 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
731 let request_url = if let Some(id) = txid {
732 format!("{}/address/{}/txs/chain/{}", self.url, address, id)
733 } else {
734 format!("{}/address/{}/txs/chain", self.url, address)
735 };
736 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
737 Ok(resp)
738 }
739
740 /// get_script_hash_txs_chain Get confirmed transaction history for the specified address/scripthash, sorted with newest first.
741 /// Returns 25 transactions per page. More can be requested by specifying the last txid seen by the previous query.
742 ///
743 /// Route : GET /scripthash/:hash/txs/chain[/:last_seen_txid]
744 ///
745 /// Example :
746 /// ````rust
747 /// use esplora_api;
748 ///
749 /// #[tokio::main]
750 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
751 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
752 /// let response = client.get_script_hash_txs_chain("c6598a8e5728c744b9734facbf1e786c3ff5101268739d38b14ea475b60eba3c",None).await?;
753 /// println!("{:?}",response);
754 /// Ok(())
755 /// }
756 /// ````
757 pub async fn get_script_hash_txs_chain(
758 &self,
759 scripthash: &str,
760 txid: Option<&str>,
761 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
762 let request_url = if let Some(id) = txid {
763 format!("{}/scripthash/{}/txs/chain/{}", self.url, scripthash, id)
764 } else {
765 format!("{}/scripthash/{}/txs/chain", self.url, scripthash)
766 };
767 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
768 Ok(resp)
769 }
770
771 /// get_address_txs_mempool Get unconfirmed transaction history for the specified address.
772 /// Returns up to 50 transactions (no paging).
773 ///
774 /// Route : GET /address/:address/txs/mempool
775 ///
776 /// Example :
777 /// ````rust
778 /// use esplora_api;
779 ///
780 /// #[tokio::main]
781 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
782 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
783 /// let response = client.get_address_txs_mempool("2MvJVm11phGoxEekPB8Hw2Tksb57eVRGHC5").await?;
784 /// println!("{:?}",response);
785 /// Ok(())
786 /// }
787 /// ````
788 pub async fn get_address_txs_mempool(
789 &self,
790 address: &str,
791 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
792 let request_url = format!("{}/address/{}/txs/mempool", self.url, address);
793 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
794 Ok(resp)
795 }
796
797 /// get_script_hash_txs_mempool Get unconfirmed transaction history for the specified scripthash.
798 /// Returns up to 50 transactions (no paging).
799 ///
800 /// Route : GET /scripthash/:hash/txs/mempool
801 ///
802 /// Example :
803 /// ````rust
804 /// use esplora_api;
805 ///
806 /// #[tokio::main]
807 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
808 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
809 /// let response = client.get_script_hash_txs_mempool("c6598a8e5728c744b9734facbf1e786c3ff5101268739d38b14ea475b60eba3c").await?;
810 /// println!("{:?}",response);
811 /// Ok(())
812 /// }
813 /// ````
814 pub async fn get_script_hash_txs_mempool(
815 &self,
816 scripthash: &str,
817 ) -> Result<Vec<TransactionFormat>, Box<dyn std::error::Error>> {
818 let request_url = format!("{}/scripthash/{}/txs/mempool", self.url, scripthash,);
819 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
820 Ok(resp)
821 }
822
823 /// get_address_utxo Get the list of unspent transaction outputs associated with the address
824 /// Available fields: txid, vout, value and status (with the status of the funding tx).
825 /// Elements-based chains have a valuecommitment field that may appear in place of value, plus the following additional fields: asset/assetcommitment, nonce/noncecommitment, surjection_proof and range_proof.
826 ///
827 /// Route : GET /address/:address/utxo
828 ///
829 /// Example :
830 /// ````rust
831 /// use esplora_api;
832 ///
833 /// #[tokio::main]
834 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
835 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
836 /// let response = client.get_address_utxo("2NDcM3CGUTwqFL7y8BSBJTYJ9kToeXawkUF").await?;
837 /// println!("{:?}",response);
838 /// Ok(())
839 /// }
840 /// ````
841 pub async fn get_address_utxo(
842 &self,
843 address: &str,
844 ) -> Result<Vec<UtxoFormat>, Box<dyn std::error::Error>> {
845 let request_url = format!("{}/address/{}/utxo", self.url, address);
846 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
847 Ok(resp)
848 }
849
850 /// get_script_hash_utxo Get the list of unspent transaction outputs associated with the address
851 /// Available fields: txid, vout, value and status (with the status of the funding tx).
852 /// Elements-based chains have a valuecommitment field that may appear in place of value, plus the following additional fields: asset/assetcommitment, nonce/noncecommitment, surjection_proof and range_proof.
853 ///
854 /// Route : GET /scripthash/:hash/utxo
855 ///
856 /// Example :
857 /// ````rust
858 /// use esplora_api;
859 ///
860 /// #[tokio::main]
861 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
862 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
863 /// let response = client.get_script_hash_utxo("c6598a8e5728c744b9734facbf1e786c3ff5101268739d38b14ea475b60eba3c").await?;
864 /// println!("{:?}",response);
865 /// Ok(())
866 /// }
867 /// ````
868 pub async fn get_script_hash_utxo(
869 &self,
870 scripthash: &str,
871 ) -> Result<Vec<UtxoFormat>, Box<dyn std::error::Error>> {
872 let request_url = format!("{}/scripthash/{}/utxo", self.url, scripthash);
873 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
874 Ok(resp)
875 }
876 /// get_address_prefix This feature is disabled by default on custom api Search for addresses beginning with :prefix.
877 /// Returns a JSON array with up to 10 results.
878 ///
879 /// Route : GET /address-prefix/:prefix
880 ///
881 /// Example :
882 /// ````rust
883 /// use esplora_api;
884 ///
885 /// #[tokio::main]
886 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
887 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
888 /// let response = client.get_address_prefix("2NDcM").await?;
889 /// println!("{:?}",response);
890 /// Ok(())
891 /// }
892 /// ````
893
894 pub async fn get_address_prefix(
895 &self,
896 prefix: &str,
897 ) -> Result<Vec<String>, Box<dyn std::error::Error>> {
898 let request_url = format!("{}/address-prefix/{}", self.url, prefix);
899 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
900 Ok(resp)
901 }
902 /// get_mempool Get mempool backlog statistics. Returns an object with:
903 /// count: the number of transactions in the mempool
904 /// vsize: the total size of mempool transactions in virtual bytes
905 /// total_fee: the total fee paid by mempool transactions in satoshis
906 /// fee_histogram: mempool fee-rate distribution histogram
907 /// An array of (feerate, vsize) tuples, where each entry's vsize is the total vsize of transactions paying more than feerate but less than the previous entry's feerate (except for the first entry, which has no upper bound). This matches the format used by the Electrum RPC protocol for mempool.get_fee_histogram.
908 ///
909 /// Route : GET /mempool
910 ///
911 /// Example :
912 /// ````rust
913 /// use esplora_api;
914 ///
915 /// #[tokio::main]
916 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
917 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
918 /// let response = client.get_mempool().await?;
919 /// println!("{:?}",response);
920 /// Ok(())
921 /// }
922 /// ````
923 /// Example output:
924 /// ````json
925 /// {
926 /// "count": 8134,
927 /// "vsize": 3444604,
928 /// "total_fee":29204625,
929 /// "fee_histogram": [[53.01, 102131], [38.56, 110990], [34.12, 138976], [24.34, 112619], [3.16, 246346], [2.92, 239701], [1.1, 775272]]
930 /// }
931 /// ````
932 /// In this example, there are transactions weighting a total of 102,131 vbytes that are paying more than 53 sat/vB, 110,990 vbytes of transactions paying between 38 and 53 sat/vB, 138,976 vbytes paying between 34 and 38, etc.
933 pub async fn get_mempool(&self) -> Result<MemPoolFormat, Box<dyn std::error::Error>> {
934 let request_url = format!("{}/mempool", self.url);
935 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
936 Ok(resp)
937 }
938 /// get_mempool_txids Get the full list of txids in the mempool as an array.
939 /// The order of the txids is arbitrary and does not match bitcoind's.
940 ///
941 /// Route : GET /mempool/txids
942 ///
943 /// Example :
944 /// ````rust
945 /// use esplora_api;
946 ///
947 /// #[tokio::main]
948 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
949 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
950 /// let response = client.get_mempool_txids().await?;
951 /// println!("{:?}",response);
952 /// Ok(())
953 /// }
954 /// ````
955 pub async fn get_mempool_txids(&self) -> Result<Vec<String>, Box<dyn std::error::Error>> {
956 let request_url = format!("{}/mempool/txids", self.url);
957 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
958 Ok(resp)
959 }
960 /// get_mempool_recent Get a list of the last 10 transactions to enter the mempool. Each transaction object contains simplified overview data, with the following fields: txid, fee, vsize and value
961 /// Fee estimates
962 /// The order of the txids is arbitrary and does not match bitcoind's.
963 ///
964 /// Route : GET /mempool/recent
965 ///
966 /// Example :
967 /// ````rust
968 /// use esplora_api;
969 ///
970 /// #[tokio::main]
971 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
972 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
973 /// let response = client.get_mempool_recent().await?;
974 /// println!("{:?}",response);
975 /// Ok(())
976 /// }
977 /// ````
978
979 pub async fn get_mempool_recent(
980 &self,
981 ) -> Result<Vec<MempoolTxFormat>, Box<dyn std::error::Error>> {
982 let request_url = format!("{}/mempool/recent", self.url);
983 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
984 Ok(resp)
985 }
986 /// fee_estimate Get an object where the key is the confirmation target (in number of blocks) and the value is the estimated feerate (in sat/vB).
987 /// The available confirmation targets are 1-25, 144, 504 and 1008 blocks.
988 /// For example: { "1": 87.882, "2": 87.882, "3": 87.882, "4": 87.882, "5": 81.129, "6": 68.285, ..., "144": 1.027, "504": 1.027, "1008": 1.027 }
989 ///
990 /// Route : GET /fee-estimates
991 ///
992 /// Example :
993 /// ````rust
994 /// use esplora_api;
995 ///
996 /// #[tokio::main]
997 /// async fn run() -> Result<(), Box<dyn std::error::Error>> {
998 /// let client = esplora_api::async_impl::ApiClient::new("https://blockstream.info/testnet/api/", None).unwrap();
999 /// let response = client.fee_estimate().await?;
1000 /// println!("{:?}",response);
1001 /// Ok(())
1002 /// }
1003 /// ````
1004
1005 pub async fn fee_estimate(&self) -> Result<HashMap<String, f32>, Box<dyn std::error::Error>> {
1006 let request_url = format!("{}/fee-estimates", self.url);
1007 let resp = self.reqwest.get(&request_url).send().await?.json().await?;
1008 Ok(resp)
1009 }
1010}