Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Api refinements #41

Merged
merged 6 commits into from
Jun 19, 2021
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,5 @@ dirs = "2.0"
dotenv = "0.15.0"
rmp-serde = "0.14.0"
tokio = { version = "1.6.0", features = ["rt-multi-thread", "macros"] }
rand = "0.8.3"
getrandom = { version = "0.2.2", features = ["js"] }
115 changes: 0 additions & 115 deletions algonaut_client/src/algod/mod.rs
Original file line number Diff line number Diff line change
@@ -1,117 +1,2 @@
use super::token::ApiToken;
use crate::error::{AlgorandError, BuilderError};
use reqwest::header::HeaderMap;
use url::Url;

pub mod v1;
pub mod v2;

/// Algod is the entry point to the creation of a client for the Algorand protocol daemon.
/// ```
/// use algonaut_client::Algod;
///
/// fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let algod = Algod::new()
/// .bind("http://localhost:4001")
/// .auth("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
/// .client_v1()?;
///
/// println!("Algod versions: {:?}", algod.versions()?.versions);
///
/// Ok(())
/// }
/// ```
pub struct Algod<'a> {
url: Option<&'a str>,
token: Option<&'a str>,
headers: HeaderMap,
}

impl<'a> Algod<'a> {
/// Start the creation of a client.
pub fn new() -> Self {
Self::default()
}

/// Bind to a URL.
pub fn bind(mut self, url: &'a str) -> Self {
self.url = Some(url);
self
}

/// Use a token to authenticate.
pub fn auth(mut self, token: &'a str) -> Self {
self.token = Some(token);
self
}

/// Build a v1 client for Algorand protocol daemon.
pub fn client_v1(self) -> Result<v1::Client, AlgorandError> {
match (self.url, self.token) {
(Some(url), Some(token)) => Ok(v1::Client {
url: Url::parse(url)?.as_ref().into(),
token: ApiToken::parse(token)?.to_string(),
headers: self.headers,
http_client: reqwest::Client::new(),
}),
(None, Some(_)) => Err(BuilderError::UnitializedUrl.into()),
(Some(_), None) => Err(BuilderError::UnitializedToken.into()),
(None, None) => Err(BuilderError::UnitializedUrl.into()),
}
}

/// Build a v2 client for Algorand protocol daemon.
pub fn client_v2(self) -> Result<v2::Client, AlgorandError> {
match (self.url, self.token) {
(Some(url), Some(token)) => Ok(v2::Client {
url: Url::parse(url)?.as_ref().into(),
token: token.to_string(),
headers: self.headers,
http_client: reqwest::Client::new(),
}),
(None, Some(_)) => Err(BuilderError::UnitializedUrl.into()),
(Some(_), None) => Err(BuilderError::UnitializedToken.into()),
(None, None) => Err(BuilderError::UnitializedUrl.into()),
}
}
}

impl<'a> Default for Algod<'a> {
fn default() -> Self {
Algod {
url: None,
token: None,
headers: HeaderMap::new(),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_valid_client_builder() {
let algod = Algod::new()
.bind("http://example.com")
.auth("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
.client_v1();

assert!(algod.ok().is_some());
}

#[test]
#[should_panic(expected = "")]
fn test_client_builder_with_no_token() {
let _ = Algod::new().bind("http://example.com").client_v1().unwrap();
}

#[test]
#[should_panic(expected = "")]
fn test_client_builder_with_no_url() {
let _ = Algod::new()
.auth("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
.client_v1()
.unwrap();
}
}
42 changes: 15 additions & 27 deletions algonaut_client/src/algod/v1/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use crate::error::AlgorandError;
use crate::extensions::reqwest::ResponseExt;
use crate::token::ApiToken;
use algonaut_core::Round;
use message::{
Account, Block, NodeStatus, PendingTransactions, QueryAccountTransactions, Supply, Transaction,
TransactionFee, TransactionId, TransactionList, TransactionParams, Version,
};
use reqwest::header::HeaderMap;
use reqwest::Url;

/// API message structs for Algorand's daemon v1
pub mod message;
Expand All @@ -14,14 +16,22 @@ const AUTH_HEADER: &str = "X-Algo-API-Token";

/// Client for interacting with the Algorand protocol daemon.
pub struct Client {
pub(super) url: String,
pub(super) token: String,
pub(super) headers: HeaderMap,
pub(super) http_client: reqwest::Client,
url: String,
token: String,
headers: HeaderMap,
http_client: reqwest::Client,
}

impl Client {
/// Returns Ok if healthy
ivnsch marked this conversation as resolved.
Show resolved Hide resolved
pub fn new(url: &str, token: &str) -> Result<Client, AlgorandError> {
Ok(Client {
url: Url::parse(url)?.as_ref().into(),
token: ApiToken::parse(token)?.to_string(),
headers: HeaderMap::new(),
http_client: reqwest::Client::new(),
})
}

pub async fn health(&self) -> Result<(), AlgorandError> {
let _ = self
.http_client
Expand All @@ -34,7 +44,6 @@ impl Client {
Ok(())
}

/// Retrieves the current version
pub async fn versions(&self) -> Result<Version, AlgorandError> {
let response = self
.http_client
Expand All @@ -50,7 +59,6 @@ impl Client {
Ok(response)
}

/// Gets the current node status
pub async fn status(&self) -> Result<NodeStatus, AlgorandError> {
let response = self
.http_client
Expand All @@ -66,7 +74,6 @@ impl Client {
Ok(response)
}

/// Waits for a block to appear after the specified round and returns the node status at the time
pub async fn status_after_block(&self, round: Round) -> Result<NodeStatus, AlgorandError> {
let response = self
.http_client
Expand All @@ -85,7 +92,6 @@ impl Client {
Ok(response)
}

/// Get the block for the given round
pub async fn block(&self, round: Round) -> Result<Block, AlgorandError> {
let response = self
.http_client
Expand All @@ -101,7 +107,6 @@ impl Client {
Ok(response)
}

/// Gets the current supply reported by the ledger
pub async fn ledger_supply(&self) -> Result<Supply, AlgorandError> {
let response = self
.http_client
Expand Down Expand Up @@ -132,9 +137,6 @@ impl Client {
Ok(response)
}

/// Gets a list of unconfirmed transactions currently in the transaction pool
///
/// Sorted by priority in decreasing order and truncated at the specified limit, or returns all if specified limit is 0
pub async fn pending_transactions(
&self,
limit: u64,
Expand All @@ -154,14 +156,6 @@ impl Client {
Ok(response)
}

/// Get a specified pending transaction
///
/// Given a transaction id of a recently submitted transaction, it returns information
/// about it. There are several cases when this might succeed: - transaction committed
/// (committed round > 0) - transaction still in the pool (committed round = 0, pool
/// error = "") - transaction removed from pool due to error (committed round = 0, pool
/// error != "") Or the transaction may have happened sufficiently long ago that the
/// node no longer remembers it, and this will return an error.
pub async fn pending_transaction_information(
&self,
transaction_id: &str,
Expand All @@ -183,7 +177,6 @@ impl Client {
Ok(response)
}

/// Get a list of confirmed transactions, limited to filters if specified
pub async fn transactions(
&self,
address: &str,
Expand All @@ -204,7 +197,6 @@ impl Client {
Ok(response)
}

/// Broadcasts a raw transaction to the network
pub async fn raw_transaction(&self, raw: &[u8]) -> Result<TransactionId, AlgorandError> {
let response = self
.http_client
Expand All @@ -222,7 +214,6 @@ impl Client {
Ok(response)
}

/// Gets the information of a single transaction
pub async fn transaction(&self, transaction_id: &str) -> Result<Transaction, AlgorandError> {
let response = self
.http_client
Expand All @@ -238,7 +229,6 @@ impl Client {
Ok(response)
}

/// Gets a specific confirmed transaction
pub async fn transaction_information(
&self,
address: &str,
Expand All @@ -261,7 +251,6 @@ impl Client {
Ok(response)
}

/// Gets suggested fee in units of micro-Algos per byte
pub async fn suggested_fee(&self) -> Result<TransactionFee, AlgorandError> {
let response = self
.http_client
Expand All @@ -277,7 +266,6 @@ impl Client {
Ok(response)
}

/// Gets parameters for constructing a new transaction
pub async fn transaction_params(&self) -> Result<TransactionParams, AlgorandError> {
let response = self
.http_client
Expand Down
Loading