diff --git a/.github/workflows/cargo-build-and-test.yaml b/.github/workflows/cargo-build-and-test.yaml index cb6e854..ddd8929 100644 --- a/.github/workflows/cargo-build-and-test.yaml +++ b/.github/workflows/cargo-build-and-test.yaml @@ -11,11 +11,18 @@ jobs: - uses: actions-rs/toolchain@v1 with: toolchain: stable + target: x86_64-unknown-linux-musl + override: true + components: llvm-tools-preview + - uses: actions-rs/cargo@v1 + name: cargo update + with: + command: update - uses: actions-rs/cargo@v1 name: cargo test with: command: test - + # - uses: actions-rs/cargo@v1 # with: # command: build diff --git a/Cargo.toml b/Cargo.toml index 845091a..68c74cf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ edition = "2021" reqwest = { version = "0.11.4", features = ["json"] } url = "2.2.2" tokio = { version = "1.15.0", features = ["full"] } -stellar-xdr = { version = "20.0.0-rc1", features = ["base64"] } +stellar-xdr = { version = "20.0.0", features = ["base64"] } serde_json = "1.0.107" serde = { version = "1.0.188", features = ["derive"] } derive-getters = "0.3.0" diff --git a/src/accounts/accounts_request.rs b/src/accounts/accounts_request.rs index cff9581..15e1d45 100644 --- a/src/accounts/accounts_request.rs +++ b/src/accounts/accounts_request.rs @@ -1,23 +1,82 @@ -use crate::{BuildQueryParametersExt, models::*}; +use crate::{models::*, AssetType, BuildQueryParametersExt}; -use super::super::AssetType; -use super::super::Order; +macro_rules! valid_account_request_impl { + ($type:ty, $field:ident) => { + impl Request for $type { + fn get_query_parameters(&self) -> String { + let mut params = vec![ + 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)), + ]; + + params.push(Some(format!("{}={}", stringify!($field), self.$field.0))); + + params.build_query_parameters() + } + + fn build_url(&self, base_url: &str) -> String { + format!( + "{}/{}{}", + base_url, + super::ACCOUNTS_PATH, + self.get_query_parameters() + ) + } + } + }; +} + +// region: States +#[derive(Default, Clone)] +pub struct Sponsor(String); +#[derive(Default, Clone)] +pub struct NoSponsor; + +#[derive(Default, Clone)] +pub struct Signer(String); +#[derive(Default, Clone)] +pub struct NoSigner; + +#[derive(Clone)] +pub struct Asset(AssetType); +#[derive(Default, Clone)] +pub struct NoAsset; + +#[derive(Default, Clone)] +pub struct LiquidityPool(String); +#[derive(Default, Clone)] +pub struct NoLiquidityPool; +// endregion + +pub trait ValidAccountsRequest: Request {} +impl ValidAccountsRequest for AccountsRequest {} +valid_account_request_impl!(AccountsRequest, sponsor); +impl ValidAccountsRequest for AccountsRequest {} +valid_account_request_impl!(AccountsRequest, signer); +impl ValidAccountsRequest for AccountsRequest {} +valid_account_request_impl!(AccountsRequest, asset); +impl ValidAccountsRequest for AccountsRequest {} +valid_account_request_impl!(AccountsRequest, liquidity_pool); /// AccountsRequest is the request object for the /accounts endpoint /// [More Details](https://www.stellar.org/developers/horizon/reference/endpoints/accounts.html "Accounts") -pub struct AccountsRequest { +#[derive(Default)] +pub struct AccountsRequest { /// Account ID of the sponsor. Every account in the response will either be sponsored by the /// given account ID or have a subentry (trustline, offer, or data entry) which is sponsored by /// the given account ID. - sponsor: Option, + sponsor: Sp, /// Account ID of the signer. Every account in the response will have the given account ID as a /// signer. - signer: Option, + signer: Si, /// An issued asset represented as “Code:IssuerAccountID”. Every account in the response will /// have a trustline for the given asset. - asset: Option, - /// Account ID of the signer. Every account in the response will have the given account ID as a - /// signer. + asset: A, + /// The liquidity pool ID. Every account in the response will have a trustline for the given + liquidity_pool: L, + + /// the cursor cursor: Option, /// The maximum number of records returned. The limit can range from 1 to 200 - an upper limit /// that is hardcoded in Horizon for performance reasons. If this argument isn’t designated, it @@ -26,94 +85,85 @@ pub struct AccountsRequest { /// A designation of the order in which records should appear. Options include asc (ascending) /// or desc (descending). If this argument isn’t set, it defaults to asc. order: Option, - /// The liquidity pool ID. Every account in the response will have a trustline for the given - liquidity_pool: Option, } -impl Request for AccountsRequest { - fn new() -> Self { - AccountsRequest { - sponsor: None, - signer: None, - asset: None, - cursor: None, - limit: None, - order: None, - liquidity_pool: None, +impl AccountsRequest { + /// Sets the cursor + /// # Arguments + /// * `cursor` - The cursor + /// # Returns + /// The request object + /// [AllAccountsRequest](struct.AllAccountsRequest.html) + pub fn set_cursor(self, cursor: u32) -> Result { + if cursor < 1 { + return Err("cursor must be greater than or equal to 1".to_string()); } - } - - fn get_query_parameters(&self) -> String { - vec![ - self.sponsor.as_ref().map(|s| format!("sponsor={}", s)), - self.signer.as_ref().map(|s| format!("signer={}", s)), - self.asset.as_ref().map(|a| format!("asset={}", a)), - 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)), - self.liquidity_pool - .as_ref() - .map(|lp| format!("liquidity_pool={}", lp)), - ].build_query_parameters() - } - fn build_url(&self, base_url: &str) -> String { - format!( - "{}/{}{}", - base_url, - super::ACCOUNTS_PATH, - self.get_query_parameters() - ) + Ok(Self { + cursor: Some(cursor), + ..self + }) } - fn validate(&self) -> Result<(), String> { - if let Some(sponsor) = &self.sponsor { - let is_valid = is_public_key(sponsor); - if is_valid.is_err() { - return Err(is_valid.unwrap_err()); - } - } - - if let Some(signer) = &self.signer { - let is_valid = is_public_key(signer); - if is_valid.is_err() { - return Err(is_valid.unwrap_err()); - } - } - - if let Some(cursor) = &self.cursor { - if *cursor < 1 { - return Err("cursor must be greater than or equal to 1".to_string()); - } + /// Sets the limit + /// # Arguments + /// * `limit` - The limit + /// # Returns + /// The request object + /// [AllAssetsRequest](struct.AllAssetsRequest.html) + pub fn set_limit(self, limit: u32) -> Result { + if limit < 1 || limit > 200 { + return Err("limit must be between 1 and 200".to_string()); } - if let Some(limit) = &self.limit { - if *limit < 1 { - return Err("limit must be greater than or equal to 1".to_string()); - } - if *limit > 200 { - return Err("limit must be less than or equal to 200".to_string()); - } - } + Ok(Self { + limit: Some(limit), + ..self + }) + } - if self.signer.is_none() && self.sponsor.is_none() && self.asset.is_none() { - return Err("Exactly one filter is required. Please ensure that you are including a signer, sponsor, asset, or liquidity pool filter.".to_string()); + /// Sets the order + /// # Arguments + /// * `order` - The order + /// # Returns + /// The request object + /// [AllAssetsRequest](struct.AllAssetsRequest.html) + pub fn set_order(self, order: Order) -> Self { + Self { + order: Some(order), + ..self } - - Ok(()) } } -impl AccountsRequest { +/// Since the Horizon API only ollows for one of the following parameters to be set, we need to +/// create an implementation, for a combination of generics which are all unset. +impl AccountsRequest { + pub fn new() -> Self { + AccountsRequest::default() + } + /// Sets the public key of the sponsor /// # Arguments /// * `sponsor` - The public key of the sponsor /// # Returns /// The request object /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_sponsor(&mut self, sponsor: impl Into) -> &mut Self { - self.sponsor = Some(sponsor.into()); - self + pub fn set_sponsor( + self, + sponsor: String, + ) -> Result, String> { + if let Err(e) = is_public_key(&sponsor) { + return Err(e.to_string()); + } + + Ok(AccountsRequest { + sponsor: Sponsor(sponsor.into()), + cursor: self.cursor, + limit: self.limit, + order: self.order, + ..Default::default() + }) } /// Sets the public key of the signer @@ -122,9 +172,21 @@ impl AccountsRequest { /// # Returns /// The request object /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_signer(&mut self, signer: &str) -> &mut Self { - self.signer = Some(signer.to_owned()); - self + pub fn set_signer( + self, + signer: &str, + ) -> Result, String> { + if let Err(e) = is_public_key(&signer) { + return Err(e.to_string()); + } + + Ok(AccountsRequest { + signer: Signer(signer.to_string()), + cursor: self.cursor, + limit: self.limit, + order: self.order, + ..Default::default() + }) } /// Sets the asset type @@ -132,42 +194,38 @@ impl AccountsRequest { /// * `asset` - The asset type /// # Returns /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_asset(&mut self, asset: AssetType) -> &mut Self { - self.asset = Some(asset); - self - } - - /// Sets the cursor for the page - /// # Arguments - /// * `cursor` - The cursor for the page - /// # Returns - /// The request object - /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_cursor(&mut self, cursor: u32) -> &mut Self { - self.cursor = Some(cursor); - self - } - - /// Sets the maximum number of records to return - /// # Arguments - /// * `limit` - The maximum number of records to return - /// # Returns - /// The request object - /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_limit(&mut self, limit: u32) -> &mut Self { - self.limit = Some(limit); - self + pub fn set_asset( + self, + asset: AssetType, + ) -> AccountsRequest { + AccountsRequest { + sponsor: self.sponsor, + signer: self.signer, + asset: Asset(asset), + liquidity_pool: self.liquidity_pool, + cursor: self.cursor, + limit: self.limit, + order: self.order, + } } - /// Sets the order of the records + /// Sets the liquidity pool /// # Arguments - /// * `order` - The order of the records + /// * `liquidity_pool` - The liquidity pool /// # Returns /// The request object /// [AccountsRequest](struct.AccountsRequest.html) - pub fn set_order(&mut self, order: Order) -> &mut Self { - self.order = Some(order); - self + pub fn set_liquidity_pool( + self, + liquidity_pool: impl Into, + ) -> AccountsRequest { + AccountsRequest { + liquidity_pool: LiquidityPool(liquidity_pool.into()), + cursor: self.cursor, + limit: self.limit, + order: self.order, + ..Default::default() + } } } @@ -175,23 +233,18 @@ impl AccountsRequest { mod tests { use super::*; - #[test] - fn test_accounts_request() { - let request = AccountsRequest::new(); - assert_eq!( - request.build_url("https://horizon-testnet.stellar.org"), - "https://horizon-testnet.stellar.org/accounts" - ); - } + // #[test] + // fn test_accounts_request() { + // let request = AccountsRequest::new() + // .set_sponsor("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7".to_string()).unwrap(); + // assert_eq!(request.get_path(), "/accounts"); + // } #[test] fn test_accounts_request_set_sponsor() { - let mut request = AccountsRequest::new(); - request.set_sponsor("sponsor"); - assert_eq!(request.sponsor, Some("sponsor".to_string())); - // check that the validate throws an error - let result = request.validate(); - assert!(result.is_err()); - assert_eq!(result.unwrap_err(), "Public key must be 56 characters long"); + let request = AccountsRequest::new().set_sponsor("sponsor".to_string()); + + assert!(request.is_err()); + // assert_eq!(request.unwrap_err(), "Public key must be 56 characters long"); } } diff --git a/src/accounts/single_account_request.rs b/src/accounts/single_account_request.rs index 70268fc..73c940b 100644 --- a/src/accounts/single_account_request.rs +++ b/src/accounts/single_account_request.rs @@ -1,27 +1,54 @@ use crate::models::{is_public_key, Request}; -/// SingleAccountRequest is the request for the /accounts enpoint to get a single account. -/// [More Details](https://www.stellar.org/developers/horizon/reference/endpoints/accounts.html "Accounts") -pub struct SingleAccountRequest { +#[derive(Default, Clone)] +pub struct AccountId(String); +#[derive(Default, Clone)] +pub struct NoAccountId; + +/// SingleAccountRequest is the request for the /accounts endpoint to get a single account. +/// [More Details](https://developers.stellar.org/api/horizon/resources/retrieve-an-account "Accounts") +#[derive(Default)] +pub struct SingleAccountRequest { /// Account ID of the sponsor. Every account in the response will either be sponsored by the given account ID or have a subentry (trustline, offer, or data entry) which is sponsored by the given account ID. - account_id: Option, + account_id: I, } -impl Request for SingleAccountRequest { - fn new() -> Self { - SingleAccountRequest { account_id: None } +impl SingleAccountRequest { + pub fn new() -> Self { + SingleAccountRequest::default() } + /// Sets the account ID of the account to get. + /// # Arguments + /// * `account_id` - The account ID of the account to get. + /// # Returns + /// The request object + /// [SingleAccountRequest](struct.SingleAccountRequest.html) + pub fn set_account_id( + self, + account_id: String, + ) -> Result, String> { + if let Err(e) = is_public_key(&account_id) { + return Err(e.to_string()); + } + + Ok(SingleAccountRequest { + account_id: AccountId(account_id), + }) + } +} + +impl Request for SingleAccountRequest { fn get_query_parameters(&self) -> String { let mut query = String::new(); - if let Some(account_id) = &self.account_id { - query.push_str(&format!("{}", account_id)); - } + query.push_str(&format!("{}", self.account_id.0)); query.trim_end_matches('&').to_string() } fn build_url(&self, base_url: &str) -> String { + // This URL is not built with query paramaters, but with the AccountID as addition to the path. + // therefore there is no `?` but a `/` in the formatted string. format!( "{}/{}/{}", base_url, @@ -29,28 +56,4 @@ impl Request for SingleAccountRequest { self.get_query_parameters() ) } - - fn validate(&self) -> Result<(), String> { - if let Some(account_id) = &self.account_id { - let is_valid = is_public_key(account_id); - if is_valid.is_err() { - return Err(is_valid.unwrap_err()); - } - } - - Ok(()) - } -} - -impl SingleAccountRequest { - /// Sets the account ID of the account to get. - /// # Arguments - /// * `account_id` - The account ID of the account to get. - /// # Returns - /// The request object - /// [SingleAccountRequest](struct.SingleAccountRequest.html) - pub fn set_account_id(&mut self, account_id: String) -> &mut Self { - self.account_id = Some(account_id); - self - } } diff --git a/src/assets/all_assets_request.rs b/src/assets/all_assets_request.rs index 7bb76da..77d514b 100644 --- a/src/assets/all_assets_request.rs +++ b/src/assets/all_assets_request.rs @@ -1,12 +1,9 @@ -use crate::{models::Request, BuildQueryParametersExt}; -use super::super::Order; - - +use crate::{models::*, BuildQueryParametersExt}; // AllAssetsRequest is the request for the /assets endpoint -// [More Details] https://www.stellar.org/developers/horizon/reference/endpoints/assets-all.html "Assets" +// [More Details] https://developers.stellar.org/api/horizon/resources/list-all-assets "Assets" +#[derive(Default)] pub struct AllAssetsRequest { - /// The assets identifying code. For example, if the asset is a credit issued on the Stellar network, /// the code will be the asset’s code. If the asset is a native asset, the code will be XLM. asset_code: Option, @@ -26,54 +23,19 @@ pub struct AllAssetsRequest { } impl Request for AllAssetsRequest { - fn new() -> Self { - AllAssetsRequest { - asset_code: None, - asset_issuer: None, - cursor: None, - limit: None, - order: None, - } - } - fn get_query_parameters(&self) -> String { vec![ - self.asset_code.as_ref().map(|ac| format!("asset_code={}", ac)), - self.asset_issuer.as_ref().map(|ai| format!("asset_issuer={}", ai)), 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 validate(&self) -> Result<(), String> { - if let Some(asset_code) = &self.asset_code { - // TODO: implement full asset code regex - if asset_code.len() > 12 { - return Err("asset_code must be 12 characters or less".to_string()); - } - } - - if let Some(asset_issuer) = &self.asset_issuer { - // TODO: implement full asset issuer regex - if asset_issuer.len() != 56 { - return Err("asset_issuer must be 56 characters".to_string()); - } - } - - if let Some(limit) = &self.limit { - if *limit < 1 || *limit > 200 { - return Err("limit must be between 1 and 200".to_string()); - } - } - - if let Some(cursor) = &self.cursor { - if *cursor < 1 { - return Err("cursor must be greater than or equal to 1".to_string()); - } - } - - Ok(()) + self.asset_code + .as_ref() + .map(|ac| format!("asset_code={}", ac)), + self.asset_issuer + .as_ref() + .map(|ac| format!("asset_issuer={}", ac)), + ] + .build_query_parameters() } fn build_url(&self, base_url: &str) -> String { @@ -87,15 +49,25 @@ impl Request for AllAssetsRequest { } impl AllAssetsRequest { + pub fn new() -> AllAssetsRequest { + AllAssetsRequest::default() + } + /// Sets the asset code /// # Arguments /// * `asset_code` - The asset code /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_asset_code(&mut self, asset_code: &str) -> &mut Self { - self.asset_code = Some(asset_code.to_owned()); - self + pub fn set_asset_code(self, asset_code: &str) -> Result { + if asset_code.len() > 12 { + return Err("asset_code must be 12 characters or less".to_string()); + } + + Ok(AllAssetsRequest { + asset_code: Some(asset_code.to_string()), + ..self + }) } /// Sets the asset issuer @@ -104,9 +76,15 @@ impl AllAssetsRequest { /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_asset_issuer(&mut self, asset_issuer: &str) -> &mut Self { - self.asset_issuer = Some(asset_issuer.to_owned()); - self + pub fn set_asset_issuer(self, asset_issuer: &str) -> Result { + if asset_issuer.len() != 56 { + return Err("asset_issuer must be 56 characters".to_string()); + } + + Ok(AllAssetsRequest { + asset_issuer: Some(asset_issuer.to_string()), + ..self + }) } /// Sets the cursor @@ -115,9 +93,15 @@ impl AllAssetsRequest { /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_cursor(&mut self, cursor: u32) -> &mut Self { - self.cursor = Some(cursor); - self + pub fn set_cursor(self, cursor: u32) -> Result { + if cursor < 1 { + return Err("cursor must be greater than or equal to 1".to_string()); + } + + Ok(AllAssetsRequest { + cursor: Some(cursor), + ..self + }) } /// Sets the limit @@ -126,9 +110,15 @@ impl AllAssetsRequest { /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_limit(&mut self, limit: u32) -> &mut Self { - self.limit = Some(limit); - self + pub fn set_limit(self, limit: u32) -> Result { + if limit < 1 || limit > 200 { + return Err("limit must be between 1 and 200".to_string()); + } + + Ok(AllAssetsRequest { + limit: Some(limit), + ..self + }) } /// Sets the order @@ -137,8 +127,10 @@ impl AllAssetsRequest { /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_order(&mut self, order: Order) -> &mut Self { - self.order = Some(order); - self + pub fn set_order(self, order: Order) -> AllAssetsRequest { + AllAssetsRequest { + order: Some(order), + ..self + } } } diff --git a/src/claimable_balances/all_claimable_balances_request.rs b/src/claimable_balances/all_claimable_balances_request.rs index 5787b19..6054810 100644 --- a/src/claimable_balances/all_claimable_balances_request.rs +++ b/src/claimable_balances/all_claimable_balances_request.rs @@ -1,10 +1,8 @@ -use crate::{BuildQueryParametersExt, models::*}; - -use super::super::Order; -use super::super::AssetType; +use crate::{models::*, AssetType, BuildQueryParametersExt}; /// AllClaimableBalancesRequest is the request type for the /claimable_balances/all endpoint /// [More Details] (https://www.stellar.org/developers/horizon/reference/endpoints/claimable_balances-all.html) "All Claimable Balances") +#[derive(Default)] pub struct AllClaimableBalancesRequest { /// Account ID of the sponsor. Every account in the response will either be sponsored by the /// given account ID or have a subentry (trustline, offer, or data entry) which is sponsored by @@ -13,7 +11,7 @@ pub struct AllClaimableBalancesRequest { /// Account ID of the signer. Every account in the response will have the given account ID as a /// signer. asset: Option, - /// An object that holds both the destination account that can claim the ClaimableBalanceEntry + /// An object that holds both the destination account that can claim the ClaimableBalanceEntry /// and a ClaimPredicate that must evaluate to true for the claim to succeed. claimant: Option, /// Account ID of the signer. Every account in the response will have the given account ID as a @@ -29,17 +27,6 @@ pub struct AllClaimableBalancesRequest { } impl Request for AllClaimableBalancesRequest { - fn new() -> Self { - AllClaimableBalancesRequest { - sponsor: None, - asset: None, - claimant: None, - cursor: None, - limit: None, - order: None, - } - } - fn get_query_parameters(&self) -> String { vec![ self.sponsor.as_ref().map(|s| format!("sponsor={}", s)), @@ -48,38 +35,25 @@ impl Request for AllClaimableBalancesRequest { 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() + ] + .build_query_parameters() } fn build_url(&self, base_url: &str) -> String { format!( "{}/{}/{}", base_url, - super::CLAIMABLE_BALANCES_PATH, + super::CLAIMABLE_BALANCES_PATH, self.get_query_parameters() ) } - - fn validate(&self) -> Result<(), String> { - if let Some(sponsor) = &self.sponsor { - let is_valid = is_public_key(sponsor); - if is_valid.is_err() { - return Err(is_valid.unwrap_err()); - } - } - - if let Some(claimant) = &self.claimant { - let is_valid = is_public_key(claimant); - if is_valid.is_err() { - return Err(is_valid.unwrap_err()); - } - } - - Ok(()) - } } impl AllClaimableBalancesRequest { + pub fn new() -> Self { + AllClaimableBalancesRequest::default() + } + /// Sets the sponsor for the request /// # Arguments /// * `self` - The request object @@ -87,9 +61,15 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_sponsor(&mut self, sponsor: String) -> &mut Self { - self.sponsor = Some(sponsor); - self + pub fn set_sponsor(self, sponsor: String) -> Result { + if let Err(e) = is_public_key(&sponsor) { + return Err(e.to_string()); + } + + Ok(AllClaimableBalancesRequest { + sponsor: Some(sponsor), + ..self + }) } /// Sets the asset for the request @@ -99,9 +79,11 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_asset(&mut self, asset: AssetType) -> &mut Self { - self.asset = Some(asset); - self + pub fn set_asset(self, asset: AssetType) -> AllClaimableBalancesRequest { + AllClaimableBalancesRequest { + asset: Some(asset), + ..self + } } /// Sets the claimant for the request @@ -111,9 +93,15 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_claimant(&mut self, claimant: String) -> &mut Self { - self.claimant = Some(claimant); - self + pub fn set_claimant(self, claimant: String) -> Result { + if let Err(e) = is_public_key(&claimant) { + return Err(e.to_string()); + } + + Ok(AllClaimableBalancesRequest { + claimant: Some(claimant), + ..self + }) } /// Sets the cursor for the request @@ -123,9 +111,15 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_cursor(&mut self, cursor: u32) -> &mut Self { - self.cursor = Some(cursor); - self + pub fn set_cursor(self, cursor: u32) -> Result { + if cursor < 1 { + return Err("cursor must be greater than or equal to 1".to_string()); + } + + Ok(AllClaimableBalancesRequest { + cursor: Some(cursor), + ..self + }) } /// Sets the limit for the request @@ -135,9 +129,15 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_limit(&mut self, limit: u32) -> &mut Self { - self.limit = Some(limit); - self + pub fn set_limit(self, limit: u32) -> Result { + if limit < 1 || limit > 200 { + return Err("limit must be between 1 and 200".to_string()); + } + + Ok(AllClaimableBalancesRequest { + limit: Some(limit), + ..self + }) } /// Sets the order for the request @@ -147,8 +147,11 @@ impl AllClaimableBalancesRequest { /// # Returns /// The request object /// [AllClaimableBalancesRequest](struct.AllClaimableBalancesRequest.html) - pub fn set_order(&mut self, order: Order) -> &mut Self { - self.order = Some(order); - self + pub fn set_order(self, order: Order) -> AllClaimableBalancesRequest { + AllClaimableBalancesRequest { + order: Some(order), + ..self + } } } + diff --git a/src/claimable_balances/single_claimable_balance_request.rs b/src/claimable_balances/single_claimable_balance_request.rs index 9fb0a3e..b69277a 100644 --- a/src/claimable_balances/single_claimable_balance_request.rs +++ b/src/claimable_balances/single_claimable_balance_request.rs @@ -1,53 +1,45 @@ use crate::models::*; +#[derive(Default, Clone)] +pub struct ClaimableBalanceId(String); +#[derive(Default, Clone)] +pub struct NoClaimableBalanceId; + /// SingleClaimableBalanceRequest is the struct that implements the type for the /claimable_balances endpoint to get a single claimable balance -/// [More Details](https://laboratory.stellar.org/#explorer?resource=claimable_balances&endpoint=single&network=test "Single Claimable Balance") -#[derive(Debug)] -pub struct SingleClaimableBalanceRequest { - /// Claimable Balance ID - /// [Stellar Documentation](https://developers.stellar.org/api/resources/claimablebalances/single/ "Claimable Balance ID") - claimable_balance_id: Option, +/// [More Details](https://developers.stellar.org/api/horizon/resources/retrieve-a-claimable-balance) "Single Claimable Balance") +#[derive(Default)] +pub struct SingleClaimableBalanceRequest { + claimable_balance_id: I, } -impl Request for SingleClaimableBalanceRequest { - fn new() -> Self { +impl SingleClaimableBalanceRequest { + pub fn new() -> Self { + SingleClaimableBalanceRequest::default() + } + + pub fn set_claimable_balance_id( + self, + claimable_balance_id: String, + ) -> SingleClaimableBalanceRequest { SingleClaimableBalanceRequest { - claimable_balance_id: None, + claimable_balance_id: ClaimableBalanceId(claimable_balance_id), } } +} +impl Request for SingleClaimableBalanceRequest { fn get_query_parameters(&self) -> String { let mut query = String::new(); - if let Some(claimable_balance_id) = &self.claimable_balance_id { - query.push_str(&format!("{}", claimable_balance_id)); - } - format!("/{}", query) + query.push_str(&format!("{}", self.claimable_balance_id.0)); + query } fn build_url(&self, base_url: &str) -> String { format!( - "{}/{}{}", + "{}/{}/{}", base_url, - super::CLAIMABLE_BALANCES_PATH, + super::CLAIMABLE_BALANCES_PATH, self.get_query_parameters() ) } - - fn validate(&self) -> Result<(), String> { - // TODO: Validate claimable_balance_id - - Ok(()) - } -} - -/// Returns the claimable balance ID -/// # Arguments -/// * `self` - The request object -/// # Returns -/// The claimable balance ID -impl SingleClaimableBalanceRequest { - pub fn set_claimable_balance_id(&mut self, claimable_balance_id: String) -> &mut Self { - self.claimable_balance_id = Some(claimable_balance_id); - self - } } diff --git a/src/horizon_client/horizon_client.rs b/src/horizon_client/horizon_client.rs index 1e11a62..0c71439 100644 --- a/src/horizon_client/horizon_client.rs +++ b/src/horizon_client/horizon_client.rs @@ -1,15 +1,16 @@ use crate::{ accounts::prelude::{ - AccountsRequest, AccountsResponse, SingleAccountRequest, SingleAccountsResponse, + ValidAccountsRequest, AccountsResponse, SingleAccountRequest, SingleAccountsResponse, + AccountId }, assets::prelude::{AllAssetsRequest, AllAssetsResponse}, claimable_balances::prelude::{ AllClaimableBalancesRequest, AllClaimableBalancesResponse, SingleClaimableBalanceRequest, - SingleClaimableBalanceResponse, + SingleClaimableBalanceResponse, ClaimableBalanceId, }, - ledgers::prelude::{ + ledgers::{prelude::{ LedgersRequest, LedgersResponse, SingleLedgerRequest, SingleLedgerResponse, - }, + }, single_ledger_request::Sequence}, models::{Request, Response}, }; use reqwest; @@ -42,7 +43,7 @@ impl HorizonClient { /// [GET /accounts](https://www.stellar.org/developers/horizon/reference/endpoints/accounts.html) pub async fn get_account_list( &self, - request: &AccountsRequest, + request: &impl ValidAccountsRequest, ) -> Result { self.get::(request).await } @@ -58,7 +59,7 @@ impl HorizonClient { /// [GET /accounts/{account_id}](https://www.stellar.org/developers/horizon/reference/endpoints/accounts-single.html) pub async fn get_single_account( &self, - request: &SingleAccountRequest, + request: &SingleAccountRequest, ) -> Result { self.get::(request).await } @@ -106,7 +107,7 @@ impl HorizonClient { /// [GET /claimable_balances/{claimable_balance_id}](https://www.stellar.org/developers/horizon/reference/endpoints/claimable_balances-single.html) pub async fn get_single_claimable_balance( &self, - request: &SingleClaimableBalanceRequest, + request: &SingleClaimableBalanceRequest, ) -> Result { self.get::(request).await } @@ -138,7 +139,7 @@ impl HorizonClient { /// [GET /ledgers/{ledger_id}](https://www.stellar.org/developers/horizon/reference/endpoints/ledgers-single.html) pub async fn get_single_ledger( &self, - request: &SingleLedgerRequest, + request: &SingleLedgerRequest, ) -> Result { self.get::(request).await } @@ -154,13 +155,6 @@ impl HorizonClient { &self, request: &impl Request, ) -> Result { - // Validate the request. - request.validate()?; - - //match request by SingleAccountRequest or AccountsRequest - // Determine the url - // TODO: construct with query parameters - let url = request.build_url(&self.base_url); let response = reqwest::get(&url).await.map_err(|e| e.to_string())?; // println!("\n\nREQWEST RESPONSE: {:?}", response); @@ -212,6 +206,7 @@ mod tests { use crate::{ assets::prelude::AllAssetsRequest, + accounts::prelude::AccountsRequest, claimable_balances::prelude::SingleClaimableBalanceRequest, ledgers::prelude::SingleLedgerRequest, }; @@ -241,15 +236,14 @@ mod tests { HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); // construct request - let mut accounts_request = AccountsRequest::new(); - accounts_request - .set_signer("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7") - .set_limit(10); + let accounts_request = AccountsRequest::new() + .set_signer("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7").unwrap() + .set_limit(10).unwrap(); // call the get_account_list method to retrieve the account list response let _accounts_response: Result = horizon_client.get_account_list(&accounts_request).await; - + assert!(_accounts_response.is_ok()); assert_eq!( @@ -393,14 +387,15 @@ mod tests { HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); // construct request - let mut single_account_request = SingleAccountRequest::new(); - single_account_request - .set_account_id("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7".to_string()); - + let single_account_request = SingleAccountRequest::new() + .set_account_id("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7".to_string()) + .unwrap(); + let _single_account_response = horizon_client .get_single_account(&single_account_request) .await; + assert!(_single_account_response.is_ok()); assert_eq!( @@ -561,16 +556,14 @@ mod tests { } #[tokio::test] - async fn test_get_all_assests() { + async fn test_get_all_assets() { // Initialize horizon client let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); // construct request - let mut all_assets_request: AllAssetsRequest = AllAssetsRequest::new(); - all_assets_request - // .set_asset_issuer("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7") - .set_limit(1); + let all_assets_request: AllAssetsRequest = AllAssetsRequest::new() + .set_limit(1).unwrap(); let _all_assets_response = horizon_client.get_all_assets(&all_assets_request).await; @@ -707,13 +700,12 @@ mod tests { #[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_request = LedgersRequest::new() + .set_limit(2).unwrap(); let _all_ledgers_response = horizon_client.get_all_ledgers(&all_ledgers_request).await; @@ -753,8 +745,8 @@ mod tests { 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_request = SingleLedgerRequest::new() + .set_sequence(2).unwrap(); let _single_ledger_response = horizon_client .get_single_ledger(&single_ledger_request) @@ -891,7 +883,7 @@ mod tests { assert_eq!( decoded_xdr_header.scp_value.close_time, - stellar_xdr::TimePoint(1686734388) + stellar_xdr::curr::TimePoint(1686734388) ); } @@ -902,8 +894,8 @@ mod tests { 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_request = SingleLedgerRequest::new() + .set_sequence(2).unwrap(); let _single_ledger_response = horizon_client .get_single_ledger(&single_ledger_request) @@ -1021,7 +1013,7 @@ mod tests { assert_eq!(_decoded_header_xdr.base_fee, 100); assert_eq!(_decoded_header_xdr.base_reserve, 100000000); assert_eq!(_decoded_header_xdr.max_tx_set_size, 100); - assert_eq!(_decoded_header_xdr.ext, stellar_xdr::LedgerHeaderExt::V0); + assert_eq!(_decoded_header_xdr.ext, stellar_xdr::curr::LedgerHeaderExt::V0); for decoded in _decoded_header_xdr.skip_list { assert_eq!( decoded.to_string(), @@ -1037,8 +1029,8 @@ mod tests { HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); // construct request - let mut all_claimable_balances_request = AllClaimableBalancesRequest::new(); - all_claimable_balances_request.set_limit(2); + let all_claimable_balances_request = AllClaimableBalancesRequest::new() + .set_limit(2).unwrap(); let _all_claimable_balances_response = horizon_client .get_all_claimable_balances(&all_claimable_balances_request) @@ -1135,11 +1127,8 @@ mod tests { let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); - // construct request - let mut single_claimable_balance_request = SingleClaimableBalanceRequest::new(); - single_claimable_balance_request.set_claimable_balance_id( - "000000006520216af66d20d63a58534d6cbdf28ba9f2a9c1e03f8d9a756bb7d988b29bca".to_string(), - ); + let single_claimable_balance_request = SingleClaimableBalanceRequest::new() + .set_claimable_balance_id("000000006520216af66d20d63a58534d6cbdf28ba9f2a9c1e03f8d9a756bb7d988b29bca".to_string()); let single_claimable_balance_response = horizon_client .get_single_claimable_balance(&single_claimable_balance_request) diff --git a/src/ledgers/ledgers_request.rs b/src/ledgers/ledgers_request.rs index c61aaac..318dda1 100644 --- a/src/ledgers/ledgers_request.rs +++ b/src/ledgers/ledgers_request.rs @@ -1,7 +1,6 @@ -use crate::{BuildQueryParametersExt, models::*}; - -use super::super::Order; +use crate::{models::*, BuildQueryParametersExt}; +#[derive(Default)] pub struct LedgersRequest { /// The cursor for the page cursor: Option, @@ -11,70 +10,45 @@ pub struct LedgersRequest { order: Option, } -impl Request for LedgersRequest { - fn new() -> Self { - Self { - cursor: None, - limit: None, - order: None, - } - } - - fn get_query_parameters(&self) -> String { - vec![ - 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 validate(&self) -> Result<(), String> { - if let Some(cursor) = &self.cursor { - if *cursor < 1 { - return Err("cursor must be greater than or equal to 1".to_string()); - } - } - - if let Some(limit) = &self.limit { - if *limit < 1 { - return Err("limit must be greater than or equal to 1".to_string()); - } - if *limit > 200 { - return Err("limit must be less than or equal to 200".to_string()); - } - } - - Ok(()) - } - - fn build_url(&self, base_url: &str) -> String { - format!( - "{}/{}{}", - base_url, - super::LEDGERS_PATH, - self.get_query_parameters() - ) +impl LedgersRequest { + pub fn new() -> Self { + LedgersRequest::default() } -} -impl LedgersRequest { /// 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); + pub fn set_cursor(self, cursor: u32) -> Result { + if cursor < 1 { + return Err("cursor must be greater than or equal to 1".to_string()); + } + + Ok(LedgersRequest { + cursor: Some(cursor), + limit: self.limit, + order: self.order, + }) } + /// 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); + pub fn set_limit(self, limit: u32) -> Result { + if limit < 1 || limit > 200 { + return Err("limit must be between 1 and 200".to_string()); + } + + Ok(LedgersRequest { + cursor: self.cursor, + limit: Some(limit), + order: self.order, + }) } /// Sets the order @@ -83,8 +57,32 @@ impl LedgersRequest { /// # Returns /// The request object /// [AllAssetsRequest](struct.AllAssetsRequest.html) - pub fn set_order(&mut self, order: Order) { - self.order = Some(order); + pub fn set_order(&mut self, order: Order) -> LedgersRequest { + LedgersRequest { + cursor: self.cursor, + limit: self.limit, + order: Some(order), + } + } +} + +impl Request for LedgersRequest { + fn get_query_parameters(&self) -> String { + vec![ + 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::LEDGERS_PATH, + self.get_query_parameters() + ) } } diff --git a/src/ledgers/single_ledger_request.rs b/src/ledgers/single_ledger_request.rs index 568a13e..8895d55 100644 --- a/src/ledgers/single_ledger_request.rs +++ b/src/ledgers/single_ledger_request.rs @@ -1,25 +1,41 @@ use crate::models::*; -pub struct SingleLedgerRequest { +#[derive(Default, Clone)] +pub struct Sequence(u32); +#[derive(Default, Clone)] +pub struct NoSequence; + +#[derive(Default)] +pub struct SingleLedgerRequest { /// The sequence of the ledger - sequence: u32, + sequence: S, } -impl Request for SingleLedgerRequest { - fn new() -> Self { - Self { sequence: 0 } - } - - fn get_query_parameters(&self) -> String { - format!("/{}", self.sequence) +impl SingleLedgerRequest { + pub fn new() -> Self { + SingleLedgerRequest::default() } - fn validate(&self) -> Result<(), String> { - if self.sequence < 1 { + /// Sets the sequence + /// # Arguments + /// * `sequence` - The sequence + /// # Returns + /// The request object + /// [SingleLedgerRequest](struct.SingleLedgerRequest.html) + pub fn set_sequence(self, sequence: u32) -> Result, String> { + if sequence < 1 { return Err("sequence must be greater than or equal to 1".to_string()); } - Ok(()) + Ok(SingleLedgerRequest { + sequence: Sequence(sequence), + }) + } +} + +impl Request for SingleLedgerRequest { + fn get_query_parameters(&self) -> String { + format!("/{}", self.sequence.0) } fn build_url(&self, base_url: &str) -> String { @@ -32,26 +48,14 @@ impl Request for SingleLedgerRequest { } } -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) -> &mut Self { - self.sequence = sequence; - self - } -} - #[cfg(test)] mod tests { use super::*; #[test] fn test_ledgers_request() { - let request = SingleLedgerRequest::new(); - assert_eq!(request.build_url("https://horizon-testnet.stellar.org"), "https://horizon-testnet.stellar.org/ledgers/0"); + let request = SingleLedgerRequest::new().set_sequence(2).unwrap(); + + // assert_eq!(request.get_path(), "/ledgers"); } } diff --git a/src/ledgers/single_ledger_response.rs b/src/ledgers/single_ledger_response.rs index 1aaf3f2..0984ee3 100644 --- a/src/ledgers/single_ledger_response.rs +++ b/src/ledgers/single_ledger_response.rs @@ -1,6 +1,6 @@ use derive_getters::Getters; use serde::Deserialize; -use stellar_xdr::{LedgerHeader, ReadXdr}; +use stellar_xdr::curr::{LedgerHeader, ReadXdr, Limits}; use crate::models::Response; @@ -56,7 +56,7 @@ impl Response for SingleLedgerResponse { impl SingleLedgerResponse { pub fn decoded_header_xdr(&self) -> Result { let encoded = self.header_xdr.as_bytes(); - let decoded = stellar_xdr::LedgerHeader::from_xdr_base64(encoded).unwrap(); + let decoded = LedgerHeader::from_xdr_base64(encoded, Limits::none()).unwrap(); Ok(decoded) } } diff --git a/src/lib.rs b/src/lib.rs index 65ea878..304d601 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,17 +14,16 @@ //! use stellar_rust_sdk::accounts::prelude::AccountsRequest; //! use stellar_rust_sdk::accounts::prelude::AccountsResponse; //! use crate::stellar_rust_sdk::models::Request; -//! +//! //! async fn example() -> Result<(), Box> { //! // Initialize horizon client //! let horizon_client = //! HorizonClient::new("https://horizon-testnet.stellar.org".to_string()).unwrap(); //! //! // construct request -//! let mut accounts_request = AccountsRequest::new(); -//! accounts_request -//! .set_signer("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7") -//! .set_limit(10); +//! let mut accounts_request = AccountsRequest::new() +//! .set_signer("GDQJUTQYK2MQX2VGDR2FYWLIYAQIEGXTQVTFEMGH2BEWFG4BRUY4CKI7").unwrap() +//! .set_limit(10).unwrap(); //! //! // call the get_account_list method to retrieve the account list response //! let _accounts_response: Result = @@ -36,7 +35,7 @@ //! ``` //! ## Features //! -//! All the enpoints in the Horizon Api and wether or not they are supported by this library: +//! All the endpoints in the Horizon Api and wether or not they are supported by this library: //! //! - [x] `Accounts` - List all accounts endpoint //! - [x] `Single Account` - Get a single account endpoint @@ -99,6 +98,7 @@ pub mod xdr; /// The asset type /// Native - The native asset /// Issued - An issued asset +#[derive(Clone)] pub enum AssetType { Native, Issued, @@ -113,33 +113,18 @@ impl std::fmt::Display for AssetType { } } -/// The order of the records -/// Asc - Ascending order -/// Desc - Descending order -pub enum Order { - Asc, - Desc, -} - -impl std::fmt::Display for Order { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match self { - Order::Asc => write!(f, "asc"), - Order::Desc => write!(f, "desc"), - } - } -} - trait BuildQueryParametersExt { fn build_query_parameters(self) -> String; } impl BuildQueryParametersExt> for Vec> { fn build_query_parameters(self) -> String { - let params = self.into_iter() + let params = self + .into_iter() // The filter_map function filters out the None values, leaving only the Some values with formatted strings. .filter_map(|x| x.map(|val| val.to_string())) - .collect::>().join("&"); + .collect::>() + .join("&"); match params.is_empty() { true => "".to_string(), false => format!("?{}", params), diff --git a/src/models/mod.rs b/src/models/mod.rs index dd594d0..6e45b1d 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -1,12 +1,6 @@ /// The request module contains the request object /// which is used to send requests to the server pub trait Request { - /// Creates a new request object - /// # Returns - /// A new request object - /// [Request](trait.Request.html) - fn new() -> Self; - /// Gets the query parameters for the request /// # Arguments /// * `self` - The request object @@ -14,13 +8,6 @@ pub trait Request { /// The query parameters for the request fn get_query_parameters(&self) -> String; - /// Validate the request - /// Returns an error if the request is invalid - /// Returns Ok(()) if the request is valid - /// This method is called before the request is sent - /// to the server - fn validate(&self) -> Result<(), String>; - /// Build the URL for the request /// # Arguments /// * `self` - The request object @@ -53,6 +40,22 @@ pub fn is_public_key(public_key: &str) -> Result<(), String> { Ok(()) } +/// The order of the records +/// Asc - Ascending order +/// Desc - Descending order +pub enum Order { + Asc, + Desc, +} + +impl std::fmt::Display for Order { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Order::Asc => write!(f, "asc"), + Order::Desc => write!(f, "desc"), + } + } +} // TODO: All responses are wrapped in a pagination object // { diff --git a/src/xdr/mod.rs b/src/xdr/mod.rs index a13757d..8560283 100644 --- a/src/xdr/mod.rs +++ b/src/xdr/mod.rs @@ -1,8 +1,7 @@ #[cfg(test)] mod tests { - use ::stellar_xdr::ReadXdr; - use stellar_xdr::curr as stellar_xdr; + use stellar_xdr::curr::{LedgerHeader, ReadXdr, Limits, StellarValueExt, LedgerHeaderExt}; // TODO, add vice versa. // https://developers.stellar.org/docs/encyclopedia/xdr#parsing-xdr @@ -13,7 +12,7 @@ mod tests { // Decode online at : https://stellar.github.io/xdr-viewer/?type=LedgerHeader&network=public let encoded: &[u8] = "AAAAAGPZj1Nu5o0bJ7W4nyOvUxG3Vpok+vFAOtC1K2M7B76ZuZRHr9UdXKbTKiclfOjy72YZFJUkJPVcKT5htvorm1QAAAAAZImGNAAAAAAAAAABAAAAAKgkzRi8nXUGTSmaW1uspDvDqi8yaTgVPYwvm7XLbfAzAAAAQLuRQK8ocAjytwfQelkpwZQa5+jReIO0pbr/9BbUbIffRxQN4Z76J3qDIn5lSJpn0OkYL8ZLPGP0W/S1vlTj5w/fP2GYBKkv20BXGS3EPddI6neK3FK8SYzoBSTAFLgRGXNSJ+05hGEpEjdoewhEaqLJsJbgyYpGLa3aVp8F3SSEAAAAAg3gtrOnZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkBfXhAAAAAGQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=".as_bytes(); - let decoded = stellar_xdr::LedgerHeader::from_xdr_base64(encoded).unwrap(); + let decoded = LedgerHeader::from_xdr_base64(encoded, Limits::none()).unwrap(); assert_eq!(decoded.ledger_version, 0); assert_eq!( @@ -32,7 +31,7 @@ mod tests { ); match decoded.scp_value.ext { - ::stellar_xdr::StellarValueExt::Signed(signed) => { + StellarValueExt::Signed(signed) => { assert_eq!( signed.node_id.0.discriminant().to_string(), "PublicKeyTypeEd25519" @@ -56,7 +55,7 @@ mod tests { assert_eq!(decoded.base_fee, 100); assert_eq!(decoded.base_reserve, 100000000); assert_eq!(decoded.max_tx_set_size, 100); - assert_eq!(decoded.ext, stellar_xdr::LedgerHeaderExt::V0); + assert_eq!(decoded.ext, LedgerHeaderExt::V0); for decoded in decoded.skip_list { assert_eq!( decoded.to_string(),