esplora: returning curl::Error

Signed-off-by: Vincenzo Palazzo <vincenzopalazzodev@gmail.com>
This commit is contained in:
Vincenzo Palazzo 2024-03-12 20:18:26 +01:00
parent 23dc837eec
commit 026ad4decf
Signed by: vincenzopalazzo
GPG Key ID: 8B6DC2B870B80D5F
1 changed files with 14 additions and 11 deletions

View File

@ -1,30 +1,31 @@
//! Esplora API //! Esplora API
//! //!
//! Author: Vincenzo Palazzo <vincenzopalazzo@member.fsf.org> //! Author: Vincenzo Palazzo <vincenzopalazzo@member.fsf.org>
use std::io;
use curl::easy::Easy; use curl::easy::Easy;
use curl::Error;
use serde_json as json; use serde_json as json;
type Result<T> = core::result::Result<T, Error>;
pub struct EsploraAPI { pub struct EsploraAPI {
base_url: String, base_url: String,
} }
impl EsploraAPI { impl EsploraAPI {
/// Create a new instance of the esplora API client. /// Create a new instance of the esplora API client.
pub fn new(url: &str) -> io::Result<Self> { pub fn new(url: &str) -> Result<Self> {
Ok(Self { Ok(Self {
base_url: url.to_owned(), base_url: url.to_owned(),
}) })
} }
pub fn client(&self, addons: &str) -> io::Result<Easy> { pub fn client(&self, addons: &str) -> Result<Easy> {
let mut easy = Easy::new(); let mut easy = Easy::new();
easy.url(&format!("{}/{addons}", self.base_url))?; easy.url(&format!("{}/{addons}", self.base_url))?;
Ok(easy) Ok(easy)
} }
pub fn raw_post(&self, addons: &str, body: &[u8]) -> io::Result<Vec<u8>> { pub fn raw_post(&self, addons: &str, body: &[u8]) -> Result<Vec<u8>> {
let mut easy = self.client(addons)?; let mut easy = self.client(addons)?;
easy.post(true)?; easy.post(true)?;
easy.post_fields_copy(body)?; easy.post_fields_copy(body)?;
@ -42,7 +43,7 @@ impl EsploraAPI {
Ok(body) Ok(body)
} }
pub fn raw_call(&self, addons: &str) -> io::Result<Vec<u8>> { pub fn raw_call(&self, addons: &str) -> Result<Vec<u8>> {
let mut easy = self.client(addons)?; let mut easy = self.client(addons)?;
let mut body = Vec::new(); let mut body = Vec::new();
{ {
@ -58,21 +59,23 @@ impl EsploraAPI {
} }
// perform a generic call // perform a generic call
pub fn call<D: serde::de::DeserializeOwned>(&self, addons: &str) -> io::Result<D> { pub fn call<D: serde::de::DeserializeOwned>(&self, addons: &str) -> Result<D> {
let body = self.raw_call(addons)?; let body = self.raw_call(addons)?;
let parsed_json: D = json::from_slice(&body)?; let parsed_json: D = json::from_slice(&body).map_err(|e| {
let mut err = Error::new(400);
err.set_extra(format!("{e}"));
err
})?;
Ok(parsed_json) Ok(parsed_json)
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::io;
use super::*; use super::*;
#[test] #[test]
fn test_tip() -> io::Result<()> { fn test_tip() -> Result<()> {
let api = EsploraAPI::new("https://blockstream.info/api")?; let api = EsploraAPI::new("https://blockstream.info/api")?;
let hash = api.raw_call("blocks/tip/hash")?; let hash = api.raw_call("blocks/tip/hash")?;
let hash = String::from_utf8(hash).unwrap(); let hash = String::from_utf8(hash).unwrap();