Skip to content

Commit

Permalink
single ledger header
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonardTibben committed Oct 11, 2023
1 parent 3c3d7f7 commit 57d8c7c
Show file tree
Hide file tree
Showing 7 changed files with 296 additions and 17 deletions.
59 changes: 57 additions & 2 deletions src/horizon_client/horizon_client.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
use crate::{
accounts::prelude::{
AccountsRequest, AccountsResponse, SingleAccountRequest, SingleAccountsResponse,
},
assets::prelude::{AllAssetsRequest, AllAssetsResponse},
ledgers::prelude::{LedgersRequest, LedgersResponse, SingleLedgerRequest, SingleLedgerResponse},
models::{Request, Response},
};
use reqwest;
Expand Down Expand Up @@ -71,6 +75,20 @@ impl HorizonClient {
self.get::<AllAssetsResponse>(request).await
}

pub async fn get_all_ledgers(
&self,
request: &LedgersRequest,
) -> Result<LedgersResponse, String> {
self.get::<LedgersResponse>(request).await
}

pub async fn get_single_ledger(
&self,
request: &SingleLedgerRequest,
) -> Result<SingleLedgerResponse, String> {
self.get::<SingleLedgerResponse>(request).await
}

/// Sends a GET request to the server
/// # Arguments
/// * `TResponse` - The type of the response
Expand All @@ -88,7 +106,9 @@ impl HorizonClient {
//match request by SingleAccountRequest or AccountsRequest
// Determine the url
// TODO: construct with query parameters

let url = request.build_url(&self.base_url);
println!("\n\nURL: {}", url);
let response = reqwest::get(&url).await.map_err(|e| e.to_string())?;
let result: TResponse = handle_response(response).await?;

Expand Down Expand Up @@ -131,7 +151,7 @@ fn url_validate(url: &str) -> Result<(), String> {

#[cfg(test)]
mod tests {
use crate::assets::prelude::AllAssetsRequest;
use crate::{assets::prelude::AllAssetsRequest, ledgers::prelude::SingleLedgerRequest};

use super::*;

Expand Down Expand Up @@ -165,7 +185,8 @@ mod tests {
.set_limit(10);

// call the get_account_list method to retrieve the account list response
let _accounts_response: Result<AccountsResponse, String> = horizon_client.get_account_list(&accounts_request).await;
let _accounts_response: Result<AccountsResponse, String> =
horizon_client.get_account_list(&accounts_request).await;

assert!(_accounts_response.is_ok());
}
Expand Down Expand Up @@ -204,4 +225,38 @@ mod tests {

assert!(_all_assets_response.is_ok());
}

#[tokio::test]
async fn test_get_all_ledgers() {
// Initialize horizon client

let horizon_client =
HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap();

// construct request
let mut all_ledgers_request = LedgersRequest::new();
all_ledgers_request.set_limit(2);

let _all_ledgers_response = horizon_client.get_all_ledgers(&all_ledgers_request).await;

assert!(_all_ledgers_response.is_ok());
}

#[tokio::test]
async fn test_get_single_ledger() {
// Initialize horizon client
let horizon_client =
HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap();

// construct request
let mut single_ledger_request = SingleLedgerRequest::new();
single_ledger_request.set_sequence(2);

let _single_ledger_response = horizon_client
.get_single_ledger(&single_ledger_request)
.await;

assert!(_single_ledger_response.is_ok());
}

}
43 changes: 29 additions & 14 deletions src/ledgers/ledgers_request.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use crate::models::*;

use super::super::Order;
use super::super::AssetType;
use super::super::Order;

pub struct LedgersRequest {

/// The cursor for the page
cursor: Option<u32>,

Expand Down Expand Up @@ -66,27 +65,43 @@ impl Request for LedgersRequest {
}

fn build_url(&self, base_url: &str) -> String {
todo!()
format!(
"{}{}?{}",
base_url,
self.get_path(),
self.get_query_parameters()
)
}
}

impl LedgersRequest {
/// Sets the cursor for the page
pub fn cursor(mut self, cursor: u32) -> Self {
/// Sets the cursor
/// # Arguments
/// * `cursor` - The cursor
/// # Returns
/// The request object
/// [AllLedgersRequest](struct.AllLedgersRequest.html)
pub fn set_cursor(&mut self, cursor: u32) {
self.cursor = Some(cursor);
self
}

/// Sets the maximum number of records to return
pub fn limit(mut self, limit: u32) -> Self {
/// Sets the limit
/// # Arguments
/// * `limit` - The limit
/// # Returns
/// The request object
/// [AllAssetsRequest](struct.AllAssetsRequest.html)
pub fn set_limit(&mut self, limit: u32) {
self.limit = Some(limit);
self
}

/// Sets the order of the records
pub fn order(mut self, order: Order) -> Self {
/// Sets the order
/// # Arguments
/// * `order` - The order
/// # Returns
/// The request object
/// [AllAssetsRequest](struct.AllAssetsRequest.html)
pub fn set_order(&mut self, order: Order) {
self.order = Some(order);
self
}
}

Expand All @@ -100,4 +115,4 @@ mod tests {

assert_eq!(request.get_path(), "/ledgers");
}
}
}
75 changes: 75 additions & 0 deletions src/ledgers/ledgers_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use serde::Deserialize;

use crate::models::Response;

#[derive(Debug, Deserialize)]
struct Link {
#[serde(rename = "self")]
self_link: SelfLink,
next: Option<SelfLink>,
prev: Option<SelfLink>,
}

#[derive(Debug, Deserialize)]
struct SelfLink {
href: String,
}

#[derive(Debug, Deserialize)]
struct Records {
_links: Link,
id: String,
paging_token: String,
hash: String,
prev_hash: String,
sequence: i32,
successful_transaction_count: i32,
failed_transaction_count: i32,
operation_count: i32,
tx_set_operation_count: i32,
closed_at: String,
total_coins: String,
fee_pool: String,
base_fee_in_stroops: i32,
base_reserve_in_stroops: i32,
max_tx_set_size: i32,
protocol_version: i32,
header_xdr: String,
}

#[derive(Debug, Deserialize)]
struct Embedded {
records: Vec<Records>,
}

#[derive(Debug, Deserialize)]
pub struct LedgersResponse {
_links: Link,
_embedded: Embedded,
}

impl Response for LedgersResponse {
fn from_json(json: String) -> Result<Self, String> {
// serde_json::from_str(&json).map_err(|e| e.to_string())

let result = serde_json::from_str(&json).map_err(|e| e.to_string());

match result {
Ok(response) => {
println!("\n FROM JSON RESULT: {:?}", response);
Ok(response)
},
Err(e) => {
println!("\n FROM JSON ERROR: {:?}", e);
Err(e.to_string())
},
}

}
}

impl LedgersResponse {
pub fn get_id(&self) -> String {
self._embedded.records[0].id.clone()
}
}
4 changes: 4 additions & 0 deletions src/ledgers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
mod ledgers_request;
mod ledgers_response;
mod single_ledger_request;
mod single_ledger_response;

pub mod prelude {
pub use super::ledgers_request::*;
pub use super::ledgers_response::*;
pub use super::single_ledger_request::*;
pub use super::single_ledger_response::*;
}
64 changes: 64 additions & 0 deletions src/ledgers/single_ledger_request.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::models::*;

use super::super::AssetType;
use super::super::Order;

pub struct SingleLedgerRequest {
/// The sequence of the ledger
sequence: u32,
}

impl Request for SingleLedgerRequest {
fn new() -> Self {
Self { sequence: 0 }
}

fn get_path(&self) -> &str {
"/ledgers"
}

fn get_query_parameters(&self) -> String {
format!("{}", self.sequence)
}

fn validate(&self) -> Result<(), String> {
if self.sequence < 1 {
return Err("sequence must be greater than or equal to 1".to_string());
}

Ok(())
}

fn build_url(&self, base_url: &str) -> String {
format!(
"{}{}/{}",
base_url,
self.get_path(),
self.get_query_parameters()
)
}
}

impl SingleLedgerRequest {
/// Sets the sequence
/// # Arguments
/// * `sequence` - The sequence
/// # Returns
/// The request object
/// [SingleLedgerRequest](struct.SingleLedgerRequest.html)
pub fn set_sequence(&mut self, sequence: u32) {
self.sequence = sequence;
}
}

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

#[test]
fn test_ledgers_request() {
let request = SingleLedgerRequest::new();

assert_eq!(request.get_path(), "/ledgers");
}
}
66 changes: 66 additions & 0 deletions src/ledgers/single_ledger_response.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use serde::{Deserialize, de};
use stellar_xdr::{ReadXdr, LedgerHeader};

use crate::models::Response;

#[derive(Debug, Deserialize)]
pub struct SingleLedgerResponse {
_links: Links,
id: String,
paging_token: String,
hash: String,
prev_hash: String,
sequence: i32,
successful_transaction_count: i32,
failed_transaction_count: i32,
operation_count: i32,
tx_set_operation_count: i32,
closed_at: String,
total_coins: String,
fee_pool: String,
base_fee_in_stroops: i32,
base_reserve_in_stroops: i64,
max_tx_set_size: i32,
protocol_version: i32,
header_xdr: String,
}

#[derive(Debug, Deserialize)]
struct Links {
#[serde(rename = "self")]
self_: Link,
transactions: Link,
operations: Link,
payments: Link,
effects: Link,
}

#[derive(Debug, Deserialize)]
struct Link {
href: String,
templated: Option<bool>,
}

impl Response for SingleLedgerResponse {
fn from_json(json: String) -> Result<Self, String> {
let result = serde_json::from_str(&json).map_err(|e| e.to_string());

match result {
Ok(response) => {
Ok(response)
},
Err(e) => {
Err(e.to_string())
},
}
}
}

impl SingleLedgerResponse {

pub fn get_decoded_header_xdr(&self) -> Result<LedgerHeader, String> {
let encoded = self.header_xdr.as_bytes();
let decoded = stellar_xdr::LedgerHeader::from_xdr_base64(encoded).unwrap();
Ok(decoded)
}
}
Loading

0 comments on commit 57d8c7c

Please sign in to comment.