use num_bigint::BigInt;
use reqwest::Method;
use serde::Deserialize;
use crate::api::PostageBatchOptions;
use crate::client::request;
use crate::swarm::{BatchId, Error};
use super::PostageApi;
use super::types::{GlobalPostageBatch, PostageBatch, PostageBatchBuckets};
#[derive(Deserialize)]
struct StampsResp {
stamps: Vec<PostageBatch>,
}
#[derive(Deserialize)]
struct BatchesResp {
batches: Vec<GlobalPostageBatch>,
}
#[derive(Deserialize)]
struct BatchIdResp {
#[serde(rename = "batchID")]
batch_id: String,
}
impl PostageApi {
pub async fn get_postage_batches(&self) -> Result<Vec<PostageBatch>, Error> {
let builder = request(&self.inner, Method::GET, "stamps")?;
let res: StampsResp = self.inner.send_json(builder).await?;
Ok(res.stamps)
}
pub async fn get_postage_batch(&self, batch_id: &BatchId) -> Result<PostageBatch, Error> {
let path = format!("stamps/{}", batch_id.to_hex());
let builder = request(&self.inner, Method::GET, &path)?;
self.inner.send_json(builder).await
}
pub async fn get_postage_batch_buckets(
&self,
batch_id: &BatchId,
) -> Result<PostageBatchBuckets, Error> {
let path = format!("stamps/{}/buckets", batch_id.to_hex());
let builder = request(&self.inner, Method::GET, &path)?;
self.inner.send_json(builder).await
}
pub async fn get_global_postage_batches(&self) -> Result<Vec<GlobalPostageBatch>, Error> {
let builder = request(&self.inner, Method::GET, "batches")?;
let res: BatchesResp = self.inner.send_json(builder).await?;
Ok(res.batches)
}
pub async fn create_postage_batch(
&self,
amount: &BigInt,
depth: u8,
label: Option<&str>,
) -> Result<BatchId, Error> {
let opts = label.map(|l| PostageBatchOptions {
label: Some(l.to_string()),
..Default::default()
});
self.create_postage_batch_with_options(amount, depth, opts.as_ref())
.await
}
pub async fn create_postage_batch_with_options(
&self,
amount: &BigInt,
depth: u8,
opts: Option<&PostageBatchOptions>,
) -> Result<BatchId, Error> {
let path = format!("stamps/{amount}/{depth}");
let mut builder = request(&self.inner, Method::POST, &path)?;
if let Some(o) = opts {
let mut query: Vec<(&str, String)> = Vec::new();
if let Some(l) = &o.label {
query.push(("label", l.clone()));
}
if let Some(im) = o.immutable {
query.push(("immutable", im.to_string()));
}
if !query.is_empty() {
let q: Vec<(&str, &str)> = query.iter().map(|(k, v)| (*k, v.as_str())).collect();
builder = builder.query(&q);
}
if let Some(gp) = &o.gas_price {
builder = builder.header("Gas-Price", gp);
}
if let Some(gl) = &o.gas_limit {
builder = builder.header("Gas-Limit", gl);
}
}
let res: BatchIdResp = self.inner.send_json(builder).await?;
BatchId::from_hex(&res.batch_id)
}
pub async fn top_up_batch(&self, batch_id: &BatchId, amount: &BigInt) -> Result<(), Error> {
let path = format!("stamps/topup/{}/{amount}", batch_id.to_hex());
let builder = request(&self.inner, Method::PATCH, &path)?;
self.inner.send(builder).await?;
Ok(())
}
pub async fn dilute_batch(&self, batch_id: &BatchId, depth: u8) -> Result<(), Error> {
let path = format!("stamps/dilute/{}/{depth}", batch_id.to_hex());
let builder = request(&self.inner, Method::PATCH, &path)?;
self.inner.send(builder).await?;
Ok(())
}
}