1use std::sync::Arc;
5
6use bytes::Bytes;
7use reqwest::Method;
8use serde::{Deserialize, Serialize};
9
10use crate::client::{Inner, request};
11use crate::swarm::{BatchId, Error, Reference};
12
13#[derive(Clone, Debug)]
16pub struct ApiService {
17 pub(crate) inner: Arc<Inner>,
18}
19
20impl ApiService {
21 pub(crate) fn new(inner: Arc<Inner>) -> Self {
22 Self { inner }
23 }
24
25 pub async fn pin(&self, reference: &Reference) -> Result<(), Error> {
29 let path = format!("pins/{}", reference.to_hex());
30 let builder = request(&self.inner, Method::POST, &path)?;
31 self.inner.send(builder).await?;
32 Ok(())
33 }
34
35 pub async fn unpin(&self, reference: &Reference) -> Result<(), Error> {
37 let path = format!("pins/{}", reference.to_hex());
38 let builder = request(&self.inner, Method::DELETE, &path)?;
39 self.inner.send(builder).await?;
40 Ok(())
41 }
42
43 pub async fn get_pin(&self, reference: &Reference) -> Result<bool, Error> {
47 let path = format!("pins/{}", reference.to_hex());
48 let builder = request(&self.inner, Method::GET, &path)?;
49 match self.inner.send(builder).await {
50 Ok(_) => Ok(true),
51 Err(e) if e.status() == Some(404) => Ok(false),
52 Err(e) => Err(e),
53 }
54 }
55
56 pub async fn list_pins(&self) -> Result<Vec<Reference>, Error> {
58 let builder = request(&self.inner, Method::GET, "pins")?;
59 #[derive(Deserialize)]
60 struct Resp {
61 references: Vec<Reference>,
62 }
63 let r: Resp = self.inner.send_json(builder).await?;
64 Ok(r.references)
65 }
66
67 pub async fn create_tag(&self) -> Result<Tag, Error> {
71 let builder = request(&self.inner, Method::POST, "tags")?;
72 self.inner.send_json(builder).await
73 }
74
75 pub async fn get_tag(&self, uid: u32) -> Result<Tag, Error> {
77 let path = format!("tags/{uid}");
78 let builder = request(&self.inner, Method::GET, &path)?;
79 self.inner.send_json(builder).await
80 }
81
82 pub async fn retrieve_tag(&self, uid: u32) -> Result<Tag, Error> {
84 self.get_tag(uid).await
85 }
86
87 pub async fn list_tags(
89 &self,
90 offset: Option<u32>,
91 limit: Option<u32>,
92 ) -> Result<Vec<Tag>, Error> {
93 let mut builder = request(&self.inner, Method::GET, "tags")?;
94 if let Some(o) = offset {
95 if o > 0 {
96 builder = builder.query(&[("offset", o.to_string())]);
97 }
98 }
99 if let Some(l) = limit {
100 if l > 0 {
101 builder = builder.query(&[("limit", l.to_string())]);
102 }
103 }
104 #[derive(Deserialize)]
105 struct Resp {
106 tags: Vec<Tag>,
107 }
108 let r: Resp = self.inner.send_json(builder).await?;
109 Ok(r.tags)
110 }
111
112 pub async fn delete_tag(&self, uid: u32) -> Result<(), Error> {
114 let path = format!("tags/{uid}");
115 let builder = request(&self.inner, Method::DELETE, &path)?;
116 self.inner.send(builder).await?;
117 Ok(())
118 }
119
120 pub async fn update_tag(&self, uid: u32, tag: &Tag) -> Result<(), Error> {
122 let path = format!("tags/{uid}");
123 let body = serde_json::to_vec(tag)?;
124 let builder = request(&self.inner, Method::PATCH, &path)?
125 .header("Content-Type", "application/json")
126 .body(Bytes::from(body));
127 self.inner.send(builder).await?;
128 Ok(())
129 }
130
131 pub async fn reupload(&self, reference: &Reference, batch_id: &BatchId) -> Result<(), Error> {
135 let path = format!("stewardship/{}", reference.to_hex());
136 let builder = request(&self.inner, Method::PUT, &path)?
137 .header("swarm-postage-batch-id", batch_id.to_hex());
138 self.inner.send(builder).await?;
139 Ok(())
140 }
141
142 pub async fn is_retrievable(&self, reference: &Reference) -> Result<bool, Error> {
146 let path = format!("stewardship/{}", reference.to_hex());
147 let builder = request(&self.inner, Method::GET, &path)?;
148 #[derive(Deserialize)]
149 struct Resp {
150 is_retrievable: bool,
151 }
152 #[derive(Deserialize)]
153 struct CamelResp {
154 #[serde(rename = "isRetrievable")]
155 is_retrievable: bool,
156 }
157 let resp = self.inner.send(builder).await?;
160 let bytes = resp.bytes().await?;
161 if let Ok(r) = serde_json::from_slice::<CamelResp>(&bytes) {
162 return Ok(r.is_retrievable);
163 }
164 let r: Resp = serde_json::from_slice(&bytes)?;
165 Ok(r.is_retrievable)
166 }
167
168 pub async fn get_grantees(&self, reference: &Reference) -> Result<Vec<String>, Error> {
172 let path = format!("grantee/{}", reference.to_hex());
173 let builder = request(&self.inner, Method::GET, &path)?;
174 let v: Vec<String> = self.inner.send_json(builder).await?;
177 Ok(v)
178 }
179
180 pub async fn create_grantees(
182 &self,
183 batch_id: &BatchId,
184 grantees: &[String],
185 ) -> Result<GranteeResponse, Error> {
186 #[derive(Serialize)]
187 struct Body<'a> {
188 grantees: &'a [String],
189 }
190 let body = serde_json::to_vec(&Body { grantees })?;
191 let builder = request(&self.inner, Method::POST, "grantee")?
192 .header("Content-Type", "application/json")
193 .header("Swarm-Postage-Batch-Id", batch_id.to_hex())
194 .body(Bytes::from(body));
195 self.inner.send_json(builder).await
196 }
197
198 pub async fn patch_grantees(
200 &self,
201 batch_id: &BatchId,
202 reference: &Reference,
203 history_address: &Reference,
204 add: &[String],
205 revoke: &[String],
206 ) -> Result<GranteeResponse, Error> {
207 #[derive(Serialize)]
208 struct Body<'a> {
209 #[serde(skip_serializing_if = "<[String]>::is_empty")]
210 add: &'a [String],
211 #[serde(skip_serializing_if = "<[String]>::is_empty")]
212 revoke: &'a [String],
213 }
214 let body = serde_json::to_vec(&Body { add, revoke })?;
215 let path = format!("grantee/{}", reference.to_hex());
216 let builder = request(&self.inner, Method::PATCH, &path)?
217 .header("Content-Type", "application/json")
218 .header("Swarm-Postage-Batch-Id", batch_id.to_hex())
219 .header("Swarm-Act-History-Address", history_address.to_hex())
220 .body(Bytes::from(body));
221 self.inner.send_json(builder).await
222 }
223
224 pub async fn post_envelope(
230 &self,
231 batch_id: &BatchId,
232 reference: &Reference,
233 ) -> Result<EnvelopeResponse, Error> {
234 let path = format!("envelope/{}", reference.to_hex());
235 let builder = request(&self.inner, Method::POST, &path)?
236 .header("Swarm-Postage-Batch-Id", batch_id.to_hex());
237 self.inner.send_json(builder).await
238 }
239}
240
241#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
245pub struct GranteeResponse {
246 #[serde(rename = "ref")]
248 pub reference: String,
249 #[serde(rename = "historyref")]
251 pub history_reference: String,
252}
253
254#[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
256pub struct EnvelopeResponse {
257 pub issuer: String,
259 pub index: String,
261 pub timestamp: String,
263 pub signature: String,
265}
266
267#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
269pub struct Tag {
270 #[serde(default)]
272 pub uid: u32,
273 #[serde(default)]
275 pub name: String,
276 #[serde(default)]
278 pub total: i64,
279 #[serde(default)]
281 pub split: i64,
282 #[serde(default)]
284 pub seen: i64,
285 #[serde(default)]
287 pub stored: i64,
288 #[serde(default)]
290 pub sent: i64,
291 #[serde(default)]
293 pub synced: i64,
294 #[serde(default)]
296 pub address: String,
297 #[serde(default, rename = "startedAt")]
299 pub started_at: String,
300}