diff options
Diffstat (limited to 'ipfs-api-prelude/src')
-rw-r--r-- | ipfs-api-prelude/src/api.rs | 1159 |
1 files changed, 1157 insertions, 2 deletions
diff --git a/ipfs-api-prelude/src/api.rs b/ipfs-api-prelude/src/api.rs index dc7e06c..2fec13c 100644 --- a/ipfs-api-prelude/src/api.rs +++ b/ipfs-api-prelude/src/api.rs @@ -6,11 +6,11 @@ // copied, modified, or distributed except according to those terms. // -use crate::{request, response, Backend}; +use crate::{read::LineDecoder, request, response, Backend}; use async_trait::async_trait; use bytes::Bytes; use common_multipart_rfc7578::client::multipart; -use futures::{future, FutureExt, Stream, StreamExt, TryStreamExt}; +use futures::{future, FutureExt, Stream, TryStreamExt}; use std::{ fs::File, io::{Cursor, Read}, @@ -888,6 +888,1161 @@ pub trait IpfsApi: Backend { self.request_empty(options, None).await } + /// Flush a path's data to disk. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_flush(None); + /// let res = client.files_flush(Some("/tmp")); + /// ``` + /// + async fn files_flush( + &self, + path: Option<&str>, + ) -> Result<response::FilesFlushResponse, Self::Error> { + self.request_empty(request::FilesFlush { path }, None).await + } + + /// List directories in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_ls(None); + /// let res = client.files_ls(Some("/tmp")); + /// ``` + /// + async fn files_ls(&self, path: Option<&str>) -> Result<response::FilesLsResponse, Self::Error> { + self.files_ls_with_options(request::FilesLs { + path, + ..Default::default() + }) + .await + } + + /// List directories in MFS.. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesLs::builder() + /// // .path("/") // defaults to / + /// .unsorted(false) + /// .long(true) + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesLs { + /// path: None, // defaults to / + /// unsorted: Some(false), + /// long: Some(true), + /// }; + /// let res = client.files_ls_with_options(req); + /// ``` + /// + /// Defaults to `-U`, so the output is unsorted. + /// + async fn files_ls_with_options( + &self, + options: request::FilesLs<'_>, + ) -> Result<response::FilesLsResponse, Self::Error> { + self.request(options, None).await + } + + /// Make directories in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_mkdir("/test", false); + /// let res = client.files_mkdir("/test/nested/dir", true); + /// ``` + /// + async fn files_mkdir( + &self, + path: &str, + parents: bool, + ) -> Result<response::FilesMkdirResponse, Self::Error> { + self.files_mkdir_with_options(request::FilesMkdir { + path, + parents: Some(parents), + ..Default::default() + }) + .await + } + + /// Make directories in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesMkdir::builder() + /// .path("/test/nested/dir") + /// .parents(true) + /// .flush(false) + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesMkdir { + /// path: "/test/nested/dir", + /// parents: Some(true), + /// flush: Some(false), + /// .. Default::default() + /// }; + /// let res = client.files_mkdir_with_options(req); + /// ``` + /// + async fn files_mkdir_with_options( + &self, + options: request::FilesMkdir<'_>, + ) -> Result<response::FilesMkdirResponse, Self::Error> { + self.request_empty(options, None).await + } + + /// Copy files into MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_mv("/test/tmp.json", "/test/file.json"); + /// ``` + /// + async fn files_mv( + &self, + path: &str, + dest: &str, + ) -> Result<response::FilesMvResponse, Self::Error> { + self.files_mv_with_options(request::FilesMv { + path, + dest, + ..Default::default() + }) + .await + } + + /// Copy files into MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_mv_with_options( + /// ipfs_api::request::FilesMv { + /// path: "/test/tmp.json", + /// dest: "/test/file.json", + /// flush: Some(false), + /// } + /// ); + /// ``` + /// + async fn files_mv_with_options( + &self, + options: request::FilesMv<'_>, + ) -> Result<response::FilesMvResponse, Self::Error> { + self.request_empty(options, None).await + } + + /// Read a file in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_read("/test/file.json"); + /// ``` + /// + fn files_read(&self, path: &str) -> Box<dyn Stream<Item = Result<Bytes, Self::Error>> + Unpin> { + self.files_read_with_options(request::FilesRead { + path, + ..request::FilesRead::default() + }) + } + + /// Read a file in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesRead::builder() + /// .path("/test/file.json") + /// .offset(1024) + /// .count(8) + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesRead { + /// path: "/test/file.json", + /// offset: Some(1024), + /// count: Some(8), + /// }; + /// let res = client.files_read_with_options(req); + /// ``` + /// + fn files_read_with_options( + &self, + options: request::FilesRead, + ) -> Box<dyn Stream<Item = Result<Bytes, Self::Error>> + Unpin> { + impl_stream_api_response! { (self, options, None) => request_stream_bytes } + } + + /// Remove a file in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_rm("/test/dir", true); + /// let res = client.files_rm("/test/file.json", false); + /// ``` + /// + async fn files_rm( + &self, + path: &str, + recursive: bool, + ) -> Result<response::FilesRmResponse, Self::Error> { + self.files_rm_with_options(request::FilesRm { + path, + recursive: Some(recursive), + ..Default::default() + }) + .await + } + + /// Remove a file in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesRm::builder() + /// .path("/test/somefile.json") + /// .recursive(false) + /// .flush(false) + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesRm { + /// path: "/test/somefile.json", + /// recursive: Some(false), + /// flush: Some(false), + /// }; + /// let res = client.files_rm_with_options(req); + /// ``` + /// + async fn files_rm_with_options( + &self, + options: request::FilesRm<'_>, + ) -> Result<response::FilesRmResponse, Self::Error> { + self.request_empty(options, None).await + } + + /// Display a file's status in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_stat("/test/file.json"); + /// ``` + /// + async fn files_stat(&self, path: &str) -> Result<response::FilesStatResponse, Self::Error> { + self.files_stat_with_options(request::FilesStat { + path, + ..Default::default() + }) + .await + } + + /// Display a file's status in MFS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_stat_with_options( + /// ipfs_api::request::FilesStat { + /// path: "/test/dir/", + /// with_local: Some(true), + /// } + /// ); + /// ``` + /// + async fn files_stat_with_options( + &self, + options: request::FilesStat<'_>, + ) -> Result<response::FilesStatResponse, Self::Error> { + self.request(options, None).await + } + + /// Write to a mutable file in the filesystem. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// use std::fs::File; + /// + /// let client = IpfsClient::default(); + /// let file = File::open("test.json").unwrap(); + /// let res = client.files_write("/test/file.json", true, true, file); + /// ``` + /// + async fn files_write<R>( + &self, + path: &str, + create: bool, + truncate: bool, + data: R, + ) -> Result<response::FilesWriteResponse, Self::Error> + where + R: 'static + Read + Send + Sync, + { + let options = request::FilesWrite { + path, + create: Some(create), + truncate: Some(truncate), + ..request::FilesWrite::default() + }; + + self.files_write_with_options(options, data).await + } + + /// Write to a mutable file in the filesystem. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// use std::io::Cursor; + /// + /// let client = IpfsClient::default(); + /// let data = Cursor::new((1..128).collect::<Vec<u8>>()); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesWrite::builder() + /// .path("/test/outfile.bin") + /// .create(false) + /// .truncate(false) + /// .offset(1 << 20) + /// .flush(false) + /// // see FilesWriteBuilder for the full set of options + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesWrite { + /// path: "/test/outfile.bin", + /// create: Some(false), + /// truncate: Some(false), + /// offset: Some(1 << 20), + /// flush: Some(false), + /// .. Default::default() + /// }; + /// let res = client.files_write_with_options(req, data); + /// ``` + /// + async fn files_write_with_options<R>( + &self, + options: request::FilesWrite<'_>, + data: R, + ) -> Result<response::FilesWriteResponse, Self::Error> + where + R: 'static + Read + Send + Sync, + { + let mut form = multipart::Form::default(); + + form.add_reader("data", data); + + self.request_empty(options, Some(form)).await + } + + /// Change the cid version or hash function of the root node of a given path. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// use std::fs::File; + /// + /// let client = IpfsClient::default(); + /// let res = client.files_chcid("/test/", 1); + /// ``` + /// + /// Not specifying a byte `count` writes the entire input. + /// + async fn files_chcid( + &self, + path: &str, + cid_version: i32, + ) -> Result<response::FilesChcidResponse, Self::Error> { + self.request_empty( + request::FilesChcid { + path: Some(path), + cid_version: Some(cid_version), + ..Default::default() + }, + None, + ) + .await + } + + /// Change the cid version or hash function of the root node of a given path. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// use std::fs::File; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let req = ipfs_api::request::FilesChcid::builder() + /// .path("/test/") + /// .cid_version(1) + /// .hash("sha3-512") + /// .flush(true) + /// .build(); + /// #[cfg(not(feature = "with-builder"))] + /// let req = ipfs_api::request::FilesChcid { + /// path: Some("/test/"), + /// cid_version: Some(1), + /// hash: Some("sha3-512"), + /// flush: Some(false), + /// }; + /// let res = client.files_chcid_with_options(req); + /// ``` + /// + /// Not specifying a byte `count` writes the entire input. + /// + async fn files_chcid_with_options( + &self, + options: request::FilesChcid<'_>, + ) -> Result<response::FilesChcidResponse, Self::Error> { + self.request_empty(options, None).await + } + + /// List blocks that are both in the filestore and standard block storage. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.filestore_dups(); + /// ``` + /// + fn filestore_dups( + &self, + ) -> Box<dyn Stream<Item = Result<response::FilestoreDupsResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::FilestoreDups, None) => request_stream_json + } + } + + /// List objects in filestore. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.filestore_ls( + /// Some("QmYPP3BovR2m8UqCZxFbdXSit6SKgExxDkFAPLqiGsap4X") + /// ); + /// ``` + /// + fn filestore_ls( + &self, + cid: Option<&str>, + ) -> Box<dyn Stream<Item = Result<response::FilestoreLsResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::FilestoreLs { cid }, None) => request_stream_json + } + } + + /// Verify objects in filestore. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.filestore_verify(None); + /// ``` + /// + fn filestore_verify( + &self, + cid: Option<&str>, + ) -> Box<dyn Stream<Item = Result<response::FilestoreVerifyResponse, Self::Error>> + Unpin> + { + impl_stream_api_response! { + (self, request::FilestoreVerify{ cid }, None) => request_stream_json + } + } + + /// Download Ipfs object. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.get("/test/file.json"); + /// ``` + /// + fn get(&self, path: &str) -> Box<dyn Stream<Item = Result<Bytes, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::Get { path }, None) => request_stream_bytes + } + } + + /// Returns information about a peer. + /// + /// If `peer` is `None`, returns information about you. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.id(None); + /// let res = client.id(Some("QmSoLPppuBtQSGwKDZT2M73ULpjvfd3aZ6ha4oFGL1KrGM")); + /// ``` + /// + async fn id(&self, peer: Option<&str>) -> Result<response::IdResponse, Self::Error> { + self.request(request::Id { peer }, None).await + } + + /// Create a new keypair. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient, KeyType}; + /// + /// let client = IpfsClient::default(); + /// let res = client.key_gen("test", KeyType::Rsa, 64); + /// ``` + /// + async fn key_gen( + &self, + name: &str, + kind: request::KeyType, + size: i32, + ) -> Result<response::KeyGenResponse, Self::Error> { + self.request(request::KeyGen { name, kind, size }, None) + .await + } + + /// List all local keypairs. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.key_list(); + /// ``` + /// + async fn key_list(&self) -> Result<response::KeyListResponse, Self::Error> { + self.request(request::KeyList, None).await + } + + /// Rename a keypair. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.key_rename("key_0", "new_name", false); + /// ``` + /// + async fn key_rename( + &self, + name: &str, + new: &str, + force: bool, + ) -> Result<response::KeyRenameResponse, Self::Error> { + self.request(request::KeyRename { name, new, force }, None) + .await + } + + /// Remove a keypair. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.key_rm("key_0"); + /// ``` + /// + async fn key_rm(&self, name: &str) -> Result<response::KeyRmResponse, Self::Error> { + self.request(request::KeyRm { name }, None).await + } + + /// Change the logging level for a logger. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient, Logger, LoggingLevel}; + /// use std::borrow::Cow; + /// + /// let client = IpfsClient::default(); + /// let res = client.log_level(Logger::All, LoggingLevel::Debug); + /// let res = client.log_level( + /// Logger::Specific(Cow::Borrowed("web")), + /// LoggingLevel::Warning + /// ); + /// ``` + /// + async fn log_level( + &self, + logger: request::Logger<'_>, + level: request::LoggingLevel, + ) -> Result<response::LogLevelResponse, Self::Error> { + self.request(request::LogLevel { logger, level }, None) + .await + } + + /// List all logging subsystems. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.log_ls(); + /// ``` + /// + async fn log_ls(&self) -> Result<response::LogLsResponse, Self::Error> { + self.request(request::LogLs, None).await + } + + /// Read the event log. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.log_tail(); + /// ``` + /// + fn log_tail(&self) -> Box<dyn Stream<Item = Result<String, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::LogTail, None) |req| => { + self.request_stream(req, |res| { + Self::process_stream_response(res, LineDecoder).map_err(Self::Error::from) + }) + } + } + } + + /// List the contents of an Ipfs multihash. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.ls("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"); + /// ``` + /// + async fn ls(&self, path: &str) -> Result<response::LsResponse, Self::Error> { + self.request( + request::Ls { + path, + ..Default::default() + }, + None, + ) + .await + } + + /// List the contents of an Ipfs multihash. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// #[cfg(feature = "with-builder")] + /// let _ = client.ls_with_options(ipfs_api::request::Ls::builder() + /// .path("/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n") + /// .build() + /// ); + /// let _ = client.ls_with_options(ipfs_api::request::Ls { + /// path: "/ipfs/QmdfTbBqBPQ7VNxZEYEj14VmRuZBkqFbiwReogJgS1zR1n", + /// // Example options for fast listing + /// stream: Some(true), + /// resolve_type: Some(false), + /// size: Some(false), + /// }); + /// ``` + /// + fn ls_with_options( + &self, + options: request::Ls<'_>, + ) -> Box<dyn Stream<Item = Result<response::LsResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, options, None) => request_stream_json + } + } + + // TODO /mount + + /// Publish an IPFS path to IPNS. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.name_publish( + /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY", + /// false, + /// Some("12h"), + /// None, + /// None + /// ); + /// ``` + /// + async fn name_publish( + &self, + path: &str, + resolve: bool, + lifetime: Option<&str>, + ttl: Option<&str>, + key: Option<&str>, + ) -> Result<response::NamePublishResponse, Self::Error> { + self.request( + request::NamePublish { + path, + resolve, + lifetime, + ttl, + key, + }, + None, + ) + .await + } + + /// Resolve an IPNS name. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.name_resolve( + /// Some("/ipns/ipfs.io"), + /// true, + /// false + /// ); + /// ``` + /// + async fn name_resolve( + &self, + name: Option<&str>, + recursive: bool, + nocache: bool, + ) -> Result<response::NameResolveResponse, Self::Error> { + self.request( + request::NameResolve { + name, + recursive, + nocache, + }, + None, + ) + .await + } + + /// Output the raw bytes of an Ipfs object. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_data("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"); + /// ``` + /// + fn object_data(&self, key: &str) -> Box<dyn Stream<Item = Result<Bytes, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::ObjectData { key }, None) => request_stream_bytes + } + } + + /// Returns the diff of two Ipfs objects. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_diff( + /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY", + /// "/ipfs/QmXdNSQx7nbdRvkjGCEQgVjVtVwsHvV8NmV2a8xzQVwuFA" + /// ); + /// ``` + /// + async fn object_diff( + &self, + key0: &str, + key1: &str, + ) -> Result<response::ObjectDiffResponse, Self::Error> { + self.request(request::ObjectDiff { key0, key1 }, None).await + } + + /// Returns the data in an object. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_get("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"); + /// ``` + /// + async fn object_get(&self, key: &str) -> Result<response::ObjectGetResponse, Self::Error> { + self.request(request::ObjectGet { key }, None).await + } + + /// Returns the links that an object points to. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_links("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"); + /// ``` + /// + async fn object_links(&self, key: &str) -> Result<response::ObjectLinksResponse, Self::Error> { + self.request(request::ObjectLinks { key }, None).await + } + + /// Create a new object. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient, ObjectTemplate}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_new(None); + /// let res = client.object_new(Some(ObjectTemplate::UnixFsDir)); + /// ``` + /// + async fn object_new( + &self, + template: Option<request::ObjectTemplate>, + ) -> Result<response::ObjectNewResponse, Self::Error> { + self.request(request::ObjectNew { template }, None).await + } + + // TODO /object/patch/add-link + + // TODO /object/patch/append-data + + // TODO /object/patch/rm-link + + // TODO /object/patch/set-data + + // TODO /object/put + + /// Returns the stats for an object. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.object_stat("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"); + /// ``` + /// + async fn object_stat(&self, key: &str) -> Result<response::ObjectStatResponse, Self::Error> { + self.request(request::ObjectStat { key }, None).await + } + + // TODO /p2p/listener/close + + // TODO /p2p/listener/ls + + // TODO /p2p/listener/open + + // TODO /p2p/stream/close + + // TODO /p2p/stream/dial + + // TODO /p2p/stream/ls + + /// Pins a new object. + /// + /// The "recursive" option tells the server whether to + /// pin just the top-level object, or all sub-objects + /// it depends on. For most cases you want it to be `true`. + /// + /// Does not yet implement the "progress" agument because + /// reading it is kinda squirrelly. + /// + /// # Examples + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pin_add("QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ", true); + /// ``` + /// + async fn pin_add( + &self, + key: &str, + recursive: bool, + ) -> Result<response::PinAddResponse, Self::Error> { + self.request( + request::PinAdd { + key, + recursive: Some(recursive), + progress: false, + }, + None, + ) + .await + } + + /// Returns a list of pinned objects in local storage. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pin_ls(None, None); + /// let res = client.pin_ls( + /// Some("/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY"), + /// None + /// ); + /// let res = client.pin_ls(None, Some("direct")); + /// ``` + /// + async fn pin_ls( + &self, + key: Option<&str>, + typ: Option<&str>, + ) -> Result<response::PinLsResponse, Self::Error> { + self.request(request::PinLs { key, typ }, None).await + } + + /// Removes a pinned object from local storage. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pin_rm( + /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY", + /// false + /// ); + /// let res = client.pin_rm( + /// "/ipfs/QmVrLsEDn27sScp3k23sgZNefVTjSAL3wpgW1iWPi4MgoY", + /// true + /// ); + /// ``` + /// + async fn pin_rm( + &self, + key: &str, + recursive: bool, + ) -> Result<response::PinRmResponse, Self::Error> { + self.request(request::PinRm { key, recursive }, None).await + } + + // TODO /pin/update + + // TODO /pin/verify + + /// Pings a peer. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.ping("QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", None); + /// let res = client.ping("QmSoLV4Bbm51jM9C4gDYZQ9Cy3U6aXMJDAbzgu2fzaDs64", Some(15)); + /// ``` + /// + fn ping( + &self, + peer: &str, + count: Option<i32>, + ) -> Box<dyn Stream<Item = Result<response::PingResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::Ping { peer, count }, None) => request_stream_json + } + } + + /// List subscribed pubsub topics. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pubsub_ls(); + /// ``` + /// + async fn pubsub_ls(&self) -> Result<response::PubsubLsResponse, Self::Error> { + self.request(request::PubsubLs, None).await + } + + /// List peers that are being published to. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pubsub_peers(None); + /// let res = client.pubsub_peers(Some("feed")); + /// ``` + /// + async fn pubsub_peers( + &self, + topic: Option<&str>, + ) -> Result<response::PubsubPeersResponse, Self::Error> { + self.request(request::PubsubPeers { topic }, None).await + } + + /// Publish a message to a topic. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pubsub_pub("feed", "Hello World!"); + /// ``` + /// + async fn pubsub_pub( + &self, + topic: &str, + payload: &str, + ) -> Result<response::PubsubPubResponse, Self::Error> { + self.request_empty(request::PubsubPub { topic, payload }, None) + .await + } + + /// Subscribes to a pubsub topic. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.pubsub_sub("feed", false); + /// let res = client.pubsub_sub("feed", true); + /// ``` + /// + fn pubsub_sub( + &self, + topic: &str, + discover: bool, + ) -> Box<dyn Stream<Item = Result<response::PubsubSubResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::PubsubSub { topic, discover }, None) => request_stream_json + } + } + + /// Gets a list of local references. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.refs_local(); + /// ``` + /// + fn refs_local( + &self, + ) -> Box<dyn Stream<Item = Result<response::RefsLocalResponse, Self::Error>> + Unpin> { + impl_stream_api_response! { + (self, request::RefsLocal, None) => request_stream_json + } + } + + // TODO /repo/fsck + + // TODO /repo/gc + + // TODO /repo/stat + + // TODO /repo/verify + + // TODO /repo/version + + // TODO /resolve + + /// Shutdown the Ipfs daemon. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.shutdown(); + /// ``` + /// + async fn shutdown(&self) -> Result<response::ShutdownResponse, Self::Error> { + self.request_empty(request::Shutdown, None).await + } + + /// Returns bitswap stats. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.stats_bitswap(); + /// ``` + /// + async fn stats_bitswap(&self) -> Result<response::StatsBitswapResponse, Self::Error> { + self.request(request::StatsBitswap, None).await + } + + /// Returns bandwidth stats. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.stats_bw(); + /// ``` + /// + async fn stats_bw(&self) -> Result<response::StatsBwResponse, Self::Error> { + self.request(request::StatsBw, None).await + } + + /// Returns repo stats. + /// + /// ```no_run + /// use ipfs_api::{IpfsApi, IpfsClient}; + /// + /// let client = IpfsClient::default(); + /// let res = client.stats_repo(); + /// ``` + /// + async fn stats_repo(&self) -> Result<response::StatsRepoResponse, Self::Error> { + self.request(request::StatsRepo, None).await + } + + // TODO /swarm/addrs/listen + + /// Return a lis |