diff --git a/stellar_rust_sdk/src/order_book/details_request.rs b/stellar_rust_sdk/src/order_book/details_request.rs index d4e7e40..2ddfe06 100644 --- a/stellar_rust_sdk/src/order_book/details_request.rs +++ b/stellar_rust_sdk/src/order_book/details_request.rs @@ -89,41 +89,50 @@ impl DetailsRequest { impl Request for DetailsRequest { fn get_query_parameters(&self) -> String { - let mut query: Vec = Vec::new(); - - match &self.selling_asset.0 { - AssetType::Native => { - query.push(format!("selling_asset_type=native")); - } - AssetType::Alphanumeric4(asset) => { - query.push(format!("selling_asset_type=credit_alphanum4")); - query.push(format!("&selling_asset_code={}", asset.asset_code)); - query.push(format!("&selling_asset_issuer={}", asset.asset_issuer)); - } - AssetType::Alphanumeric12(asset) => { - query.push(format!("selling_asset_type=credit_alphanum12")); - query.push(format!("&selling_asset_code={}", asset.asset_code)); - query.push(format!("&selling_asset_issuer={}", asset.asset_issuer)); - } - } - - match &self.buying_asset.0 { - AssetType::Native => { - query.push(format!("&buying_asset_type=native")); - } - AssetType::Alphanumeric4(asset) => { - query.push(format!("&buying_asset_type=credit_alphanum4")); - query.push(format!("&buying_asset_code={}", asset.asset_code)); - query.push(format!("&buying_asset_issuer={}", asset.asset_issuer)); - } - AssetType::Alphanumeric12(asset) => { - query.push(format!("&buying_asset_type=credit_alphanum12")); - query.push(format!("&buying_asset_code={}", asset.asset_code)); - query.push(format!("&buying_asset_issuer={}", asset.asset_issuer)); - } - } - - query.join("") + vec![&self.selling_asset.0, &self.buying_asset.0] + .iter() + .enumerate() + .fold(Vec::new(), |mut parameters, (i, asset)| { + let asset_type_prefix = if i == 0 { + "selling_asset_type=" + } + // no `&` for `base_asset_type`, as the query begins with `?` + else { + "&buying_asset_type=" + }; + match asset { + AssetType::Native => parameters.push(format!("{}native", asset_type_prefix)), + AssetType::Alphanumeric4(asset_data) + | AssetType::Alphanumeric12(asset_data) => { + let asset_type = match asset { + AssetType::Alphanumeric4(_) => "credit_alphanum4", + AssetType::Alphanumeric12(_) => "credit_alphanum12", + _ => "", // should not be reached + }; + let asset_issuer_prefix = if i == 0 { + "&selling_asset_issuer=" + } else { + "&buying_asset_issuer=" + }; + let asset_code_prefix = if i == 0 { + "&selling_asset_code=" + } else { + "&buying_asset_code=" + }; + parameters.push(format!( + "{}{}{}{}{}{}", + asset_type_prefix, + asset_type, + asset_code_prefix, + asset_data.asset_code, + asset_issuer_prefix, + asset_data.asset_issuer + )); + } + } + parameters + }) + .join("") } fn build_url(&self, base_url: &str) -> String { diff --git a/stellar_rust_sdk/src/trades/all_trades_request.rs b/stellar_rust_sdk/src/trades/all_trades_request.rs index f7cb7bc..f01b76f 100644 --- a/stellar_rust_sdk/src/trades/all_trades_request.rs +++ b/stellar_rust_sdk/src/trades/all_trades_request.rs @@ -1,5 +1,4 @@ -use crate::models::prelude::AssetType; -use crate::models::*; +use crate::{models::prelude::*, models::*, BuildQueryParametersExt}; use stellar_rust_sdk_derive::pagination; /// Represents the base and counter assets. Contains an enum of one of the possible asset types. @@ -91,49 +90,67 @@ impl AllTradesRequest { impl Request for AllTradesRequest { fn get_query_parameters(&self) -> String { - let mut query: Vec = Vec::new(); - - if let Some(base_asset) = &self.base_asset { - match &base_asset.0 { - AssetType::Native => { - query.push(format!("base_asset_type=native")); - } - AssetType::Alphanumeric4(asset) => { - query.push(format!("base_asset_type=credit_alphanum4")); - query.push(format!("&base_asset_code={}", asset.asset_code)); - query.push(format!("&base_asset_issuer={}", asset.asset_issuer)); + let asset_parameters = vec![&self.base_asset, &self.counter_asset] + .iter() + .enumerate() + .fold(Vec::new(), |mut parameters, (i, asset)| { + let asset_type_prefix = if i == 0 { + "base_asset_type=" } - AssetType::Alphanumeric12(asset) => { - query.push(format!("base_asset_type=credit_alphanum12")); - query.push(format!("&base_asset_code={}", asset.asset_code)); - query.push(format!("&base_asset_issuer={}", asset.asset_issuer)); + // no `&` for `base_asset_type`, as the query begins with `?` + else { + "&counter_asset_type=" + }; + match asset { + Some(TradeAsset(AssetType::Native)) => { + parameters.push(format!("{}native", asset_type_prefix)) + } + Some(TradeAsset(AssetType::Alphanumeric4(asset_data))) + | Some(TradeAsset(AssetType::Alphanumeric12(asset_data))) => { + let asset_type = match asset { + Some(TradeAsset(AssetType::Alphanumeric4(_))) => "credit_alphanum4", + Some(TradeAsset(AssetType::Alphanumeric12(_))) => "credit_alphanum12", + _ => "", // should not be reached + }; + let asset_issuer_prefix = if i == 0 { + "&base_asset_issuer=" + } else { + "&counter_asset_issuer=" + }; + let asset_code_prefix = if i == 0 { + "&base_asset_code=" + } else { + "&counter_asset_code=" + }; + parameters.push(format!( + "{}{}{}{}{}{}", + asset_type_prefix, + asset_type, + asset_code_prefix, + asset_data.asset_code, + asset_issuer_prefix, + asset_data.asset_issuer + )); + } + None => {} } - } - } + parameters + }) + .join(""); - if let Some(counter_asset) = &self.counter_asset { - match &counter_asset.0 { - AssetType::Native => { - query.push(format!("&counter_asset_type=native")); - } - AssetType::Alphanumeric4(asset) => { - query.push(format!("&counter_asset_type=credit_alphanum4")); - query.push(format!("&counter_asset_code={}", asset.asset_code)); - query.push(format!("&counter_asset_issuer={}", asset.asset_issuer)); - } - AssetType::Alphanumeric12(asset) => { - query.push(format!("&counter_asset_type=credit_alphanum12")); - query.push(format!("&counter_asset_code={}", asset.asset_code)); - query.push(format!("&counter_asset_issuer={}", asset.asset_issuer)); - } - } - } - query.join("") + vec![ + Some(asset_parameters), + self.offer_id.as_ref().map(|o| format!("offer_id={}", o)), + self.cursor.as_ref().map(|c| format!("cursor={}", c)), + self.limit.as_ref().map(|l| format!("limit={}", l)), + self.order.as_ref().map(|o| format!("order={}", o)), + ] + .build_query_parameters() } fn build_url(&self, base_url: &str) -> String { format!( - "{}/{}?{}", + "{}/{}{}", base_url, super::TRADES_PATH, self.get_query_parameters() diff --git a/stellar_rust_sdk/src/trades/mod.rs b/stellar_rust_sdk/src/trades/mod.rs index 2c43c4c..2c805bb 100644 --- a/stellar_rust_sdk/src/trades/mod.rs +++ b/stellar_rust_sdk/src/trades/mod.rs @@ -91,7 +91,7 @@ pub mod prelude { #[cfg(test)] pub mod test { - use crate::{horizon_client::HorizonClient, trades::prelude::*}; + use crate::{horizon_client::HorizonClient, models::prelude::*, trades::prelude::*}; #[tokio::test] async fn all_trades_request() { @@ -184,6 +184,27 @@ pub mod test { assert_eq!(response.base_is_seller(), BASE_IS_SELLER); assert_eq!(response.price().as_ref().unwrap().numenator(), PRICE_N); assert_eq!(response.price().as_ref().unwrap().denominator(), PRICE_R); + + // Create request with parameters. Note: valid data must be submitted to get results. + // This API endpoint will return an error if no resources were found, instead of an empty result. + // To get valid results, make an empty 'all trades request' (for example, in the Stellar Laboratory), + // and enter the results in the following request. + let all_trades_request = AllTradesRequest::new() + .set_base_asset(AssetType::Alphanumeric4(AssetData { + asset_code: "XETH".to_string(), + asset_issuer: "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI" + .to_string(), + })) + .unwrap() + .set_counter_asset(AssetType::Alphanumeric4(AssetData { + asset_code: "XUSD".to_string(), + asset_issuer: "GBZXN7PIRZGNMHGA7MUUUF4GWPY5AYPV6LY4UV2GL6VJGIQRXFDNMADI" + .to_string(), + })) + .unwrap(); + + let all_trades_response = horizon_client.get_all_trades(&all_trades_request).await; + assert!(all_trades_response.clone().is_ok()); } #[tokio::test] @@ -418,9 +439,7 @@ pub mod test { const PRICE_N: &str = "3"; const PRICE_D: &str = "10"; - let trades_for_offer_request = TradesForOfferRequest::new() - .set_offer_id(OFFER_ID) - .unwrap(); + let trades_for_offer_request = TradesForOfferRequest::new().set_offer_id(OFFER_ID).unwrap(); let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap(); let trades_for_liquidity_pools_response = horizon_client .get_trades_for_offer(&trades_for_offer_request)