bark-rest-client 0.2.5

A simple REST API for barkd, a wallet daemon for integrating bitcoin payments into your app over HTTP. Supports self-custodial Lightning, Ark, and on-chain out of the box. barkd is a long-running daemon best suited for always-on or high-connectivity environments like nodes, servers, desktops, and point-of-sale terminals. All endpoints return JSON. Amounts are denominated in satoshis.
Documentation
/*
 * barkd REST API
 *
 * A simple REST API for barkd, a wallet daemon for integrating bitcoin payments into your app over HTTP. Supports self-custodial Lightning, Ark, and on-chain out of the box.  barkd is a long-running daemon best suited for always-on or high-connectivity environments like nodes, servers, desktops, and point-of-sale terminals.  All endpoints return JSON. Amounts are denominated in satoshis.
 *
 * The version of the OpenAPI document: 0.2.5
 * Contact: hello@second.tech
 * Generated by: https://openapi-generator.tech
 */


use reqwest;
use serde::{Deserialize, Serialize, de::Error as _};
use crate::{apis::ResponseContent, models};
use super::{Error, configuration, ContentType};


/// struct for typed errors of method [`board_fee`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum BoardFeeError {
    Status400(models::BadRequestError),
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`lightning_receive_fee`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LightningReceiveFeeError {
    Status400(models::BadRequestError),
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`lightning_send_fee`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum LightningSendFeeError {
    Status400(models::BadRequestError),
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`offboard_all_fee`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OffboardAllFeeError {
    Status400(models::BadRequestError),
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`onchain_fee_rates`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OnchainFeeRatesError {
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}

/// struct for typed errors of method [`send_onchain_fee`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum SendOnchainFeeError {
    Status400(models::BadRequestError),
    Status500(models::InternalServerError),
    UnknownValue(serde_json::Value),
}


/// Estimates the Ark protocol fee for boarding the specified amount of on-chain bitcoin. The net amount is what the user receives as a VTXO. Does not include the on-chain transaction fee for the board anchor transaction.
pub async fn board_fee(configuration: &configuration::Configuration, amount_sat: i64) -> Result<models::FeeEstimateResponse, Error<BoardFeeError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_amount_sat = amount_sat;

    let uri_str = format!("{}/api/v1/fees/board", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("amount_sat", &p_query_amount_sat.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FeeEstimateResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FeeEstimateResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<BoardFeeError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}

/// Estimates the fee for receiving the specified amount over Lightning. The gross amount is the Lightning payment amount, and the net amount is what the user receives as a VTXO after the Ark server deducts its fee.
pub async fn lightning_receive_fee(configuration: &configuration::Configuration, amount_sat: i64) -> Result<models::FeeEstimateResponse, Error<LightningReceiveFeeError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_amount_sat = amount_sat;

    let uri_str = format!("{}/api/v1/fees/lightning/receive", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("amount_sat", &p_query_amount_sat.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FeeEstimateResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FeeEstimateResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<LightningReceiveFeeError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}

/// Estimates the fee for sending the specified amount over Lightning. The net amount is what the recipient receives. The fee depends on the VTXOs selected and their expiry. If the wallet has insufficient funds, returns a worst-case fee estimate assuming the user acquires enough funds to cover the payment.
pub async fn lightning_send_fee(configuration: &configuration::Configuration, amount_sat: i64) -> Result<models::FeeEstimateResponse, Error<LightningSendFeeError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_amount_sat = amount_sat;

    let uri_str = format!("{}/api/v1/fees/lightning/pay", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("amount_sat", &p_query_amount_sat.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FeeEstimateResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FeeEstimateResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<LightningSendFeeError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}

/// Estimates the fee for offboarding the entire Ark balance to the given on-chain address. The gross amount is the total spendable balance, and the net amount is what the user receives on-chain after fees. The fee depends on the destination address type, current fee rates, and VTXO expiry.
pub async fn offboard_all_fee(configuration: &configuration::Configuration, address: &str) -> Result<models::FeeEstimateResponse, Error<OffboardAllFeeError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_address = address;

    let uri_str = format!("{}/api/v1/fees/offboard-all", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("address", &p_query_address.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FeeEstimateResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FeeEstimateResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<OffboardAllFeeError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}

/// Returns the current mempool fee rates from the chain source at three confirmation targets: fast (~1 block), regular (~3 blocks), and slow (~6 blocks). Rates are in sat/vB, rounded up.
pub async fn onchain_fee_rates(configuration: &configuration::Configuration, ) -> Result<models::OnchainFeeRatesResponse, Error<OnchainFeeRatesError>> {

    let uri_str = format!("{}/api/v1/fees/onchain", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::OnchainFeeRatesResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::OnchainFeeRatesResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<OnchainFeeRatesError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}

/// Estimates the total fee for sending bitcoin from the Ark wallet to an on-chain address. The fee depends on the destination address type and current fee rates. The gross amount is what the user pays (including VTXOs spent), and the net amount is what the recipient receives on-chain.
pub async fn send_onchain_fee(configuration: &configuration::Configuration, amount_sat: i64, address: &str) -> Result<models::FeeEstimateResponse, Error<SendOnchainFeeError>> {
    // add a prefix to parameters to efficiently prevent name collisions
    let p_query_amount_sat = amount_sat;
    let p_query_address = address;

    let uri_str = format!("{}/api/v1/fees/send-onchain", configuration.base_path);
    let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);

    req_builder = req_builder.query(&[("amount_sat", &p_query_amount_sat.to_string())]);
    req_builder = req_builder.query(&[("address", &p_query_address.to_string())]);
    if let Some(ref user_agent) = configuration.user_agent {
        req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
    }
    if let Some(ref token) = configuration.bearer_access_token {
        req_builder = req_builder.bearer_auth(token.to_owned());
    };

    let req = req_builder.build()?;
    let resp = configuration.client.execute(req).await?;

    let status = resp.status();
    let content_type = resp
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("application/octet-stream");
    let content_type = super::ContentType::from(content_type);

    if !status.is_client_error() && !status.is_server_error() {
        let content = resp.text().await?;
        match content_type {
            ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
            ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::FeeEstimateResponse`"))),
            ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::FeeEstimateResponse`")))),
        }
    } else {
        let content = resp.text().await?;
        let entity: Option<SendOnchainFeeError> = serde_json::from_str(&content).ok();
        Err(Error::ResponseError(ResponseContent { status, content, entity }))
    }
}