stellar_rs/transactions/
mod.rs

1/// Provides the `SingleTransactionRequest`.
2///
3/// # Usage
4/// This module provides the `SingleTransactionRequest` struct, specifically designed for
5/// constructing requests to query information about a single transaction from the Horizon
6/// server. It is tailored for use with the [`HorizonClient::get_single_transaction`](crate::horizon_client::HorizonClient::get_single_transaction)
7/// method.
8///
9pub mod single_transaction_request;
10
11/// Provides the `PostTransactionRequest`.
12///
13/// # Usage
14/// This module provides the `PostTransactionRequest` struct, specifically designed for
15/// constructing requests to post a new transaction to the Horizon server.
16/// It is tailored for use with the [`HorizonClient::post_transaction`](crate::horizon_client::HorizonClient::post_transaction) method.
17///
18pub mod post_transaction_request;
19
20/// Provides the `AllTransactionsRequest`.
21///
22/// # Usage
23/// This module provides the `AllTransactionsRequest` struct, specifically designed for
24/// constructing requests to query information about all transactions from the Horizon
25/// server. It is tailored for use with the [`HorizonClient::get_all_transactions`](crate::horizon_client::HorizonClient::get_all_transactions)
26/// method.
27///
28pub mod all_transactions_request;
29
30/// Provides the `TransactionsForAccountRequest`.
31///
32/// # Usage
33/// This module provides the `TransactionsForAccountRequest` struct, specifically designed for
34/// constructing requests to query information about all successful transactions for a given account from the Horizon
35/// server. It is tailored for use with the [`HorizonClient::get_transactions_for_account`](crate::horizon_client::HorizonClient::get_transactions_for_account)
36/// method.
37///
38pub mod transactions_for_account_request;
39
40/// Provides the `TransactionsForLedgersRequest`.
41///
42/// # Usage
43/// This module provides the `TransactionsForLedgersRequest` struct, specifically designed for
44/// constructing requests to query information about all successful transactions in a given ledger from the Horizon
45/// server. It is tailored for use with the [`HorizonClient::get_transactions_for_ledger`](crate::horizon_client::HorizonClient::get_transactions_for_ledger)
46/// method.
47///
48pub mod transactions_for_ledger_request;
49
50/// Provides the `TransactionsForLiquidityPoolRequest`.
51///
52/// # Usage
53/// This module provides the `TransactionsForLiquidityPoolRequest` struct, specifically designed for
54/// constructing requests to query information about all successful transactions referencing
55/// a given liquidity pool from the Horizon server.
56/// It is tailored for use with the [`HorizonClient::get_transactions_for_liquidity_pool`](crate::horizon_client::HorizonClient::get_transactions_for_liquidity_pool)
57/// method.
58///
59pub mod transactions_for_liquidity_pool_request;
60
61/// Provides the responses.
62///
63/// This module defines structures representing the response from the Horizon API when querying
64/// for transactions. The structures are designed to deserialize the JSON response into Rust
65/// objects, enabling straightforward access to various details of a single transaction.
66///
67/// # Usage
68/// These structures are equipped with serialization capabilities to handle the JSON data from the
69/// Horizon server and with getter methods for easy field access.
70pub mod response;
71
72/// The base path for transaction-related endpoints in the Horizon API.
73///
74/// # Usage
75/// This variable is intended to be used internally by the request-building logic
76/// to ensure consistent and accurate path construction for transaction-related API calls.
77pub(crate) static TRANSACTIONS_PATH: &str = "transactions";
78
79/// The `prelude` module of the `transactions` module.
80///
81/// # Usage
82/// This module serves as a convenience for users of the Horizon Rust SDK, allowing for easy and
83/// ergonomic import of the most commonly used items across various modules. It re-exports
84/// key structs and traits from the sibling modules, simplifying access to these components
85/// when using the library.
86///
87/// By importing the contents of `prelude`, users can conveniently access the primary
88/// functionalities of the transaction-related modules without needing to import each item
89/// individually.
90///
91/// # Contents
92///
93/// The `prelude` includes the following re-exports:
94///
95/// * From `single_transaction_request`: All items (e.g. `SingleTransactionRequest`).
96/// * From `post_transaction_request`: All items (e.g. `PostTransactionRequest`, `TransactionEnvelope`, `NoTransactionEnvelope`).
97/// * From `all_transactions_request`: All items (e.g. `AllTransactionsRequest`).
98/// * From `transactions_for_account_request`: All items (e.g. `TransactionsForAccountRequest`, `TransactionsAccountId`, etc.).
99/// * From `transactions_for_ledger_request`: All items (e.g. `TransactionsForLedgerRequest`, `TransactionsLedgerId`, etc.).
100/// * From `transactions_for_liquidity_pool_request`: All items (e.g. `TransactionsForLiquidityPoolRequest`, `TransactionsLiquidityPoolId`, etc.).
101/// * From `response`: All items (e.g. `SingleTransactionResponse`, `Preconditions`, etc.).
102///
103/// # Example
104/// ```
105/// # use crate::stellar_rs::models::*;
106/// // Import the contents of the transactions prelude
107/// use stellar_rs::transactions::prelude::*;
108///
109/// // Now you can directly use SingleTransactionRequest, SingleTransactionResponse, etc.
110/// let single_transactions_request = SingleTransactionRequest::new();
111/// ```
112pub mod prelude {
113    pub use super::all_transactions_request::*;
114    pub use super::post_transaction_request::*;
115    pub use super::response::*;
116    pub use super::single_transaction_request::*;
117    pub use super::transactions_for_account_request::*;
118    pub use super::transactions_for_ledger_request::*;
119    pub use super::transactions_for_liquidity_pool_request::*;
120}
121
122#[cfg(test)]
123pub mod test {
124    use super::prelude::*;
125    use crate::horizon_client::HorizonClient;
126    use crate::models::IncludeFailed;
127
128    const LINK_SELF: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
129    const LINK_ACCOUNT: &str = "https://horizon-testnet.stellar.org/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
130    const LINK_LEDGER: &str = "https://horizon-testnet.stellar.org/ledgers/539";
131    const LINK_OPERATIONS: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020/operations{?cursor,limit,order}";
132    const LINK_EFFECTS: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020/effects{?cursor,limit,order}";
133    const LINK_PRECEDES: &str =
134        "https://horizon-testnet.stellar.org/transactions?order=asc&cursor=2314987376640";
135    const LINK_SUCCEEDS: &str =
136        "https://horizon-testnet.stellar.org/transactions?order=desc&cursor=2314987376640";
137    const LINK_TRANSACTION: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
138    const ID: &str = "b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
139    const PAGING_TOKEN: &str = "2314987376640";
140    const SUCCESSFUL: &bool = &true;
141    const HASH: &str = "b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
142    const LEDGER: &i64 = &539;
143    const CREATED_AT: &str = "2024-06-11T21:36:12Z";
144    const SOURCE_ACCOUNT: &str = "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
145    const SOURCE_ACCOUNT_SEQUENCE: &str = "1";
146    const FEE_ACCOUNT: &str = "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
147    const FEE_CHARGED: &str = "1100";
148    const MAX_FEE: &str = "1100";
149    const OPERATION_COUNT: &i64 = &11;
150    // TODO: Is it necessary to test the following 4 values, as they're very long?
151    // const ENVELOPE_XDR: &str = "";
152    // const RESULT_XDR: &str = "";
153    // const RESULT_META_XDR: &str = "";
154    // const FEE_META_XDR: &str = "";
155    const MEMO_TYPE: &str = "none";
156    const SIGNATURE: &str =
157        "NUHx9PZlcXQ9mq1lf1usrSTP4/gbxUqzUOQOSU/pQuy9dF7FcUF0fjEbzFECxHUcl4QEfbvyGIE029TA3DrODA==";
158    const VALID_AFTER: &str = "1970-01-01T00:00:00Z";
159    const MIN_TIME: &str = "0";
160
161    #[tokio::test]
162    async fn test_get_single_transaction() {
163        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
164
165        let single_transaction_request = SingleTransactionRequest::new()
166            .set_transaction_hash(ID)
167            .unwrap();
168
169        let single_transaction_response = horizon_client
170            .get_single_transaction(&single_transaction_request)
171            .await;
172
173        assert!(single_transaction_response.clone().is_ok());
174        let response = single_transaction_response.unwrap();
175        assert_eq!(
176            response.links().self_link().href().as_ref().unwrap(),
177            LINK_SELF
178        );
179        assert_eq!(
180            response.links().account().href().as_ref().unwrap(),
181            LINK_ACCOUNT
182        );
183        assert_eq!(
184            response.links().ledger().href().as_ref().unwrap(),
185            LINK_LEDGER
186        );
187        assert_eq!(
188            response.links().operations().href().as_ref().unwrap(),
189            LINK_OPERATIONS
190        );
191        assert_eq!(
192            response.links().effects().href().as_ref().unwrap(),
193            LINK_EFFECTS
194        );
195        assert_eq!(
196            response.links().precedes().href().as_ref().unwrap(),
197            LINK_PRECEDES
198        );
199        assert_eq!(
200            response.links().succeeds().href().as_ref().unwrap(),
201            LINK_SUCCEEDS
202        );
203        assert_eq!(
204            response.links().transaction().href().as_ref().unwrap(),
205            LINK_TRANSACTION
206        );
207        assert_eq!(response.id(), ID);
208        assert_eq!(response.paging_token(), PAGING_TOKEN);
209        assert_eq!(response.successful(), SUCCESSFUL);
210        assert_eq!(response.hash(), HASH);
211        assert_eq!(response.ledger(), LEDGER);
212        assert_eq!(response.created_at(), CREATED_AT);
213        assert_eq!(response.source_account(), SOURCE_ACCOUNT);
214        assert_eq!(response.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
215        assert_eq!(response.fee_account(), FEE_ACCOUNT);
216        assert_eq!(response.fee_charged(), FEE_CHARGED);
217        assert_eq!(response.max_fee(), MAX_FEE);
218        assert_eq!(response.operation_count(), OPERATION_COUNT);
219        assert_eq!(response.memo_type(), MEMO_TYPE);
220        assert_eq!(response.signatures()[0], SIGNATURE);
221        assert_eq!(response.valid_after().as_ref().unwrap(), VALID_AFTER);
222        assert_eq!(
223            response
224                .preconditions()
225                .as_ref()
226                .unwrap()
227                .timebounds()
228                .min_time(),
229            MIN_TIME
230        );
231    }
232
233    #[tokio::test]
234    async fn test_get_all_transactions() {
235        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
236
237        let all_transactions_request = AllTransactionsRequest::new()
238            .set_include_failed(IncludeFailed::True)
239            .unwrap();
240
241        let all_transactions_response = horizon_client
242            .get_all_transactions(&all_transactions_request)
243            .await;
244
245        assert!(all_transactions_response.clone().is_ok());
246        let binding = all_transactions_response.unwrap();
247        let record = &binding.embedded().records()[0];
248        assert_eq!(
249            record.links().self_link().href().as_ref().unwrap(),
250            LINK_SELF
251        );
252        assert_eq!(
253            record.links().account().href().as_ref().unwrap(),
254            LINK_ACCOUNT
255        );
256        assert_eq!(
257            record.links().ledger().href().as_ref().unwrap(),
258            LINK_LEDGER
259        );
260        assert_eq!(
261            record.links().operations().href().as_ref().unwrap(),
262            LINK_OPERATIONS
263        );
264        assert_eq!(
265            record.links().effects().href().as_ref().unwrap(),
266            LINK_EFFECTS
267        );
268        assert_eq!(
269            record.links().precedes().href().as_ref().unwrap(),
270            LINK_PRECEDES
271        );
272        assert_eq!(
273            record.links().succeeds().href().as_ref().unwrap(),
274            LINK_SUCCEEDS
275        );
276        assert_eq!(
277            record.links().transaction().href().as_ref().unwrap(),
278            LINK_TRANSACTION
279        );
280        assert_eq!(record.id(), ID);
281        assert_eq!(record.paging_token(), PAGING_TOKEN);
282        assert_eq!(record.successful(), SUCCESSFUL);
283        assert_eq!(record.hash(), HASH);
284        assert_eq!(record.ledger(), LEDGER);
285        assert_eq!(record.created_at(), CREATED_AT);
286        assert_eq!(record.source_account(), SOURCE_ACCOUNT);
287        assert_eq!(record.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
288        assert_eq!(record.fee_account(), FEE_ACCOUNT);
289        assert_eq!(record.fee_charged(), FEE_CHARGED);
290        assert_eq!(record.max_fee(), MAX_FEE);
291        assert_eq!(record.operation_count(), OPERATION_COUNT);
292        assert_eq!(record.memo_type(), MEMO_TYPE);
293        assert_eq!(record.signatures()[0], SIGNATURE); // Check only the first signature of the vector
294        assert_eq!(record.valid_after().as_ref().unwrap(), VALID_AFTER);
295        assert_eq!(
296            record
297                .preconditions()
298                .as_ref()
299                .unwrap()
300                .timebounds()
301                .min_time(),
302            MIN_TIME
303        );
304    }
305
306    #[tokio::test]
307    async fn test_get_transactions_for_account() {
308        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
309
310        let transactions_for_account_request = TransactionsForAccountRequest::new()
311            .set_account_id("GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H")
312            .unwrap()
313            .set_include_failed(true)
314            .unwrap();
315
316        let transactions_for_account_response = horizon_client
317            .get_transactions_for_account(&transactions_for_account_request)
318            .await;
319
320        assert!(transactions_for_account_response.clone().is_ok());
321        let binding = transactions_for_account_response.unwrap();
322        let record = &binding.embedded().records()[0];
323        assert_eq!(
324            record.links().self_link().href().as_ref().unwrap(),
325            LINK_SELF
326        );
327        assert_eq!(
328            record.links().account().href().as_ref().unwrap(),
329            LINK_ACCOUNT
330        );
331        assert_eq!(
332            record.links().ledger().href().as_ref().unwrap(),
333            LINK_LEDGER
334        );
335        assert_eq!(
336            record.links().operations().href().as_ref().unwrap(),
337            LINK_OPERATIONS
338        );
339        assert_eq!(
340            record.links().effects().href().as_ref().unwrap(),
341            LINK_EFFECTS
342        );
343        assert_eq!(
344            record.links().precedes().href().as_ref().unwrap(),
345            LINK_PRECEDES
346        );
347        assert_eq!(
348            record.links().succeeds().href().as_ref().unwrap(),
349            LINK_SUCCEEDS
350        );
351        assert_eq!(
352            record.links().transaction().href().as_ref().unwrap(),
353            LINK_TRANSACTION
354        );
355        assert_eq!(record.id(), ID);
356        assert_eq!(record.paging_token(), PAGING_TOKEN);
357        assert_eq!(record.successful(), SUCCESSFUL);
358        assert_eq!(record.hash(), HASH);
359        assert_eq!(record.ledger(), LEDGER);
360        assert_eq!(record.created_at(), CREATED_AT);
361        assert_eq!(record.source_account(), SOURCE_ACCOUNT);
362        assert_eq!(record.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
363        assert_eq!(record.fee_account(), FEE_ACCOUNT);
364        assert_eq!(record.fee_charged(), FEE_CHARGED);
365        assert_eq!(record.max_fee(), MAX_FEE);
366        assert_eq!(record.operation_count(), OPERATION_COUNT);
367        assert_eq!(record.memo_type(), MEMO_TYPE);
368        assert_eq!(record.signatures()[0], SIGNATURE); // Check only the first signature of the vector
369        assert_eq!(record.valid_after().as_ref().unwrap(), VALID_AFTER);
370        assert_eq!(
371            record
372                .preconditions()
373                .as_ref()
374                .unwrap()
375                .timebounds()
376                .min_time(),
377            MIN_TIME
378        );
379    }
380
381    #[tokio::test]
382    async fn test_get_transactions_for_ledger() {
383        const LEDGER_SEQUENCE: &str = "539";
384
385        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
386
387        let transactions_for_ledger_request = TransactionsForLedgerRequest::new()
388            .set_ledger_sequence(LEDGER_SEQUENCE)
389            .unwrap()
390            .set_include_failed(true)
391            .unwrap();
392
393        let transactions_for_ledger_response = horizon_client
394            .get_transactions_for_ledger(&transactions_for_ledger_request)
395            .await;
396
397        assert!(transactions_for_ledger_response.clone().is_ok());
398        let binding = transactions_for_ledger_response.unwrap();
399        let record = &binding.embedded().records()[0];
400        assert_eq!(
401            record.links().self_link().href().as_ref().unwrap(),
402            LINK_SELF
403        );
404        assert_eq!(
405            record.links().account().href().as_ref().unwrap(),
406            LINK_ACCOUNT
407        );
408        assert_eq!(
409            record.links().ledger().href().as_ref().unwrap(),
410            LINK_LEDGER
411        );
412        assert_eq!(
413            record.links().operations().href().as_ref().unwrap(),
414            LINK_OPERATIONS
415        );
416        assert_eq!(
417            record.links().effects().href().as_ref().unwrap(),
418            LINK_EFFECTS
419        );
420        assert_eq!(
421            record.links().precedes().href().as_ref().unwrap(),
422            LINK_PRECEDES
423        );
424        assert_eq!(
425            record.links().succeeds().href().as_ref().unwrap(),
426            LINK_SUCCEEDS
427        );
428        assert_eq!(
429            record.links().transaction().href().as_ref().unwrap(),
430            LINK_TRANSACTION
431        );
432        assert_eq!(record.id(), ID);
433        assert_eq!(record.paging_token(), PAGING_TOKEN);
434        assert_eq!(record.successful(), SUCCESSFUL);
435        assert_eq!(record.hash(), HASH);
436        assert_eq!(record.ledger(), LEDGER);
437        assert_eq!(record.created_at(), CREATED_AT);
438        assert_eq!(record.source_account(), SOURCE_ACCOUNT);
439        assert_eq!(record.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
440        assert_eq!(record.fee_account(), FEE_ACCOUNT);
441        assert_eq!(record.fee_charged(), FEE_CHARGED);
442        assert_eq!(record.max_fee(), MAX_FEE);
443        assert_eq!(record.operation_count(), OPERATION_COUNT);
444        assert_eq!(record.memo_type(), MEMO_TYPE);
445        assert_eq!(record.signatures()[0], SIGNATURE); // Check only the first signature of the vector
446        assert_eq!(record.valid_after().as_ref().unwrap(), VALID_AFTER);
447        assert_eq!(
448            record
449                .preconditions()
450                .as_ref()
451                .unwrap()
452                .timebounds()
453                .min_time(),
454            MIN_TIME
455        );
456    }
457
458    #[tokio::test]
459    async fn test_get_transactions_for_liquidity_pool() {
460        const LINK_SELF: &str = "https://horizon-testnet.stellar.org/transactions/1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6";
461        const LINK_ACCOUNT: &str = "https://horizon-testnet.stellar.org/accounts/GDB4ZUD465ZQ2FQZ4GNHEWVYJKZVOGSMJOEUGMFVLOOARFS4YKMRBCRV";
462        const LINK_LEDGER: &str = "https://horizon-testnet.stellar.org/ledgers/106867";
463        const LINK_OPERATIONS: &str = "https://horizon-testnet.stellar.org/transactions/1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6/operations{?cursor,limit,order}";
464        const LINK_EFFECTS: &str = "https://horizon-testnet.stellar.org/transactions/1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6/effects{?cursor,limit,order}";
465        const LINK_PRECEDES: &str =
466            "https://horizon-testnet.stellar.org/transactions?order=asc&cursor=458990270087168";
467        const LINK_SUCCEEDS: &str =
468            "https://horizon-testnet.stellar.org/transactions?order=desc&cursor=458990270087168";
469        const LINK_TRANSACTION: &str = "https://horizon-testnet.stellar.org/transactions/1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6";
470        const ID: &str = "1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6";
471        const PAGING_TOKEN: &str = "458990270087168";
472        const SUCCESSFUL: &bool = &true;
473        const HASH: &str = "1f6abb2a00ba84469f8d95271bf2eec99da10bddb894be11f29f7a7039f0c0a6";
474        const LEDGER: &i64 = &106867;
475        const CREATED_AT: &str = "2024-06-18T08:54:13Z";
476        const SOURCE_ACCOUNT: &str = "GDB4ZUD465ZQ2FQZ4GNHEWVYJKZVOGSMJOEUGMFVLOOARFS4YKMRBCRV";
477        const SOURCE_ACCOUNT_SEQUENCE: &str = "458960205250561";
478        const FEE_ACCOUNT: &str = "GDB4ZUD465ZQ2FQZ4GNHEWVYJKZVOGSMJOEUGMFVLOOARFS4YKMRBCRV";
479        const FEE_CHARGED: &str = "100";
480        const MAX_FEE: &str = "100";
481        const OPERATION_COUNT: &i64 = &1;
482        const MEMO_TYPE: &str = "none";
483        const SIGNATURE: &str = "T8ediCtghc8L41mZpHLfWGe0a6pe+wfr1cdaHLApD6Kv0nKrQ6FK/biBWf50IrsMQjMfK61m3a997qQc3M3oDA==";
484        const VALID_AFTER: &str = "1970-01-01T00:00:00Z";
485        const MIN_TIME: &str = "0";
486
487        const LIQUIDITY_POOL_ID: &str =
488            "0066b15f5d0dc0be771209c33f3e4126383e58183a598eae8b3813024c6a6d10";
489
490        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
491
492        let transactions_for_liquidity_pool_request = TransactionsForLiquidityPoolRequest::new()
493            .set_liquidity_pool_id(LIQUIDITY_POOL_ID)
494            .unwrap()
495            .set_include_failed(true)
496            .unwrap();
497
498        let transactions_for_liquidity_pool_response = horizon_client
499            .get_transactions_for_liquidity_pool(&transactions_for_liquidity_pool_request)
500            .await;
501
502        assert!(transactions_for_liquidity_pool_response.clone().is_ok());
503        let binding = transactions_for_liquidity_pool_response.unwrap();
504        let record = &binding.embedded().records()[0];
505        assert_eq!(
506            record.links().self_link().href().as_ref().unwrap(),
507            LINK_SELF
508        );
509        assert_eq!(
510            record.links().account().href().as_ref().unwrap(),
511            LINK_ACCOUNT
512        );
513        assert_eq!(
514            record.links().ledger().href().as_ref().unwrap(),
515            LINK_LEDGER
516        );
517        assert_eq!(
518            record.links().operations().href().as_ref().unwrap(),
519            LINK_OPERATIONS
520        );
521        assert_eq!(
522            record.links().effects().href().as_ref().unwrap(),
523            LINK_EFFECTS
524        );
525        assert_eq!(
526            record.links().precedes().href().as_ref().unwrap(),
527            LINK_PRECEDES
528        );
529        assert_eq!(
530            record.links().succeeds().href().as_ref().unwrap(),
531            LINK_SUCCEEDS
532        );
533        assert_eq!(
534            record.links().transaction().href().as_ref().unwrap(),
535            LINK_TRANSACTION
536        );
537        assert_eq!(record.id(), ID);
538        assert_eq!(record.paging_token(), PAGING_TOKEN);
539        assert_eq!(record.successful(), SUCCESSFUL);
540        assert_eq!(record.hash(), HASH);
541        assert_eq!(record.ledger(), LEDGER);
542        assert_eq!(record.created_at(), CREATED_AT);
543        assert_eq!(record.source_account(), SOURCE_ACCOUNT);
544        assert_eq!(record.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
545        assert_eq!(record.fee_account(), FEE_ACCOUNT);
546        assert_eq!(record.fee_charged(), FEE_CHARGED);
547        assert_eq!(record.max_fee(), MAX_FEE);
548        assert_eq!(record.operation_count(), OPERATION_COUNT);
549        assert_eq!(record.memo_type(), MEMO_TYPE);
550        assert_eq!(record.signatures()[0], SIGNATURE); // Check only the first signature of the vector
551        assert_eq!(record.valid_after().as_ref().unwrap(), VALID_AFTER);
552        assert_eq!(
553            record
554                .preconditions()
555                .as_ref()
556                .unwrap()
557                .timebounds()
558                .min_time(),
559            MIN_TIME
560        );
561    }
562
563    #[tokio::test]
564    async fn test_post_transaction() {
565        const REQUEST_XDR: &str = "AAAAAgAAAABi/B0L0JGythwN1lY0aypo19NHxvLCyO5tBEcCVvwF9wAABEwAAAAAAAAAAQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsAAAAAAAAAAAAAAAAQfdFrLDgzSIIugR73qs8U0ZiKbwBUclTTPh5thlbgnAFjRXhdigAAAAAAAAAAAAAAAAAA3b5KF6uk1w1fSKYLrzR8gF2lB+AHAi6oU6CaWhunAskAAAAXSHboAAAAAAAAAAAAAAAAAHfmNeMLin2aTUfxa530ZRn4zwRu7ROAQfUJeJco8HSCAAHGv1JjQAAAAAAAAAAAAAAAAAAAlRt2go9sp7E1a5ZWvr7vin4UPrFQThpQax1lOFm33AAAABdIdugAAAAAAAAAAAAAAAAAmv+knlR6JR2VqWeU0k/4FgvZ/tSV5DEY4gu0iOTKgpUAAAAXSHboAAAAAAAAAAAAAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bAAAAF0h26AAAAAABAAAAAACVG3aCj2ynsTVrlla+vu+KfhQ+sVBOGlBrHWU4WbfcAAAABgAAAAFURVNUAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bf/////////8AAAABAAAAAJr/pJ5UeiUdlalnlNJP+BYL2f7UleQxGOILtIjkyoKVAAAABgAAAAFURVNUAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bf/////////8AAAABAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bAAAAAQAAAAAAlRt2go9sp7E1a5ZWvr7vin4UPrFQThpQax1lOFm33AAAAAFURVNUAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bAAAJGE5yoAAAAAABAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bAAAAAQAAAACa/6SeVHolHZWpZ5TST/gWC9n+1JXkMRjiC7SI5MqClQAAAAFURVNUAAAAANpaWLojuOtfC0cmMh+DvQTfPDrkfXhblQTdFXrGYc0bAAAJGE5yoAAAAAAAAAAAAAAAAABKBB+2UBMP/abwcm/M1TXO+/JQWhPwkalgqizKmXyRIQx7qh6aAFYAAAAAAAAAAARW/AX3AAAAQDVB8fT2ZXF0PZqtZX9brK0kz+P4G8VKs1DkDklP6ULsvXRexXFBdH4xG8xRAsR1HJeEBH278hiBNNvUwNw6zgzGYc0bAAAAQLgZUU/oYGL7frWDQhJHhCQu9JmfqN03PrJq4/cJrN1OSUWXnmLc94sv8m2L+cxl2p0skr2Jxy+vt1Lcxkv7wAI4WbfcAAAAQHvZEVqlygIProf3jVTZohDWm2WUNrFAFXf1LctTqDCQBHph14Eo+APwrTURLLYTIvNoXeGzBKbL03SsOARWcQLkyoKVAAAAQHAvKv2/Ro4+cNh6bKQO/G9NNiUozYysGwG1GvJQkFjwy/OTsL6WBfuI0Oye84lVBVrQVk2EY1ERFhgdMpuFSg4=";
566
567        const LINK_SELF: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
568        const LINK_ACCOUNT: &str = "https://horizon-testnet.stellar.org/accounts/GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
569        const LINK_LEDGER: &str = "https://horizon-testnet.stellar.org/ledgers/539";
570        const LINK_OPERATIONS: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020/operations{?cursor,limit,order}";
571        const LINK_EFFECTS: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020/effects{?cursor,limit,order}";
572        const LINK_PRECEDES: &str =
573            "https://horizon-testnet.stellar.org/transactions?order=asc&cursor=2314987376640";
574        const LINK_SUCCEEDS: &str =
575            "https://horizon-testnet.stellar.org/transactions?order=desc&cursor=2314987376640";
576        const LINK_TRANSACTION: &str = "https://horizon-testnet.stellar.org/transactions/b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
577        const ID: &str = "b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
578        const PAGING_TOKEN: &str = "2314987376640";
579        const SUCCESSFUL: &bool = &true;
580        const HASH: &str = "b9d0b2292c4e09e8eb22d036171491e87b8d2086bf8b265874c8d182cb9c9020";
581        const LEDGER: &i64 = &539;
582        const CREATED_AT: &str = "2024-06-11T21:36:12Z";
583        const SOURCE_ACCOUNT: &str = "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
584        const SOURCE_ACCOUNT_SEQUENCE: &str = "1";
585        const FEE_ACCOUNT: &str = "GBRPYHIL2CI3FNQ4BXLFMNDLFJUNPU2HY3ZMFSHONUCEOASW7QC7OX2H";
586        const FEE_CHARGED: &str = "1100";
587        const MAX_FEE: &str = "1100";
588        const OPERATION_COUNT: &i64 = &11;
589        const MEMO_TYPE: &str = "none";
590        const SIGNATURE: &str = "NUHx9PZlcXQ9mq1lf1usrSTP4/gbxUqzUOQOSU/pQuy9dF7FcUF0fjEbzFECxHUcl4QEfbvyGIE029TA3DrODA==";
591        const VALID_AFTER: &str = "1970-01-01T00:00:00Z";
592        const MIN_TIME: &str = "0";
593
594        let horizon_client = HorizonClient::new("https://horizon-testnet.stellar.org").unwrap();
595
596        let request = PostTransactionRequest::new()
597            .set_transaction_envelope_xdr(REQUEST_XDR)
598            .unwrap();
599
600        let response = horizon_client.post_transaction(&request).await;
601
602        assert!(response.clone().is_ok());
603        let record = response.unwrap();
604        assert_eq!(
605            record.links().self_link().href().as_ref().unwrap(),
606            LINK_SELF
607        );
608        assert_eq!(
609            record.links().account().href().as_ref().unwrap(),
610            LINK_ACCOUNT
611        );
612        assert_eq!(
613            record.links().ledger().href().as_ref().unwrap(),
614            LINK_LEDGER
615        );
616        assert_eq!(
617            record.links().operations().href().as_ref().unwrap(),
618            LINK_OPERATIONS
619        );
620        assert_eq!(
621            record.links().effects().href().as_ref().unwrap(),
622            LINK_EFFECTS
623        );
624        assert_eq!(
625            record.links().precedes().href().as_ref().unwrap(),
626            LINK_PRECEDES
627        );
628        assert_eq!(
629            record.links().succeeds().href().as_ref().unwrap(),
630            LINK_SUCCEEDS
631        );
632        assert_eq!(
633            record.links().transaction().href().as_ref().unwrap(),
634            LINK_TRANSACTION
635        );
636        assert_eq!(record.id(), ID);
637        assert_eq!(record.paging_token(), PAGING_TOKEN);
638        assert_eq!(record.successful(), SUCCESSFUL);
639        assert_eq!(record.hash(), HASH);
640        assert_eq!(record.ledger(), LEDGER);
641        assert_eq!(record.created_at(), CREATED_AT);
642        assert_eq!(record.source_account(), SOURCE_ACCOUNT);
643        assert_eq!(record.source_account_sequence(), SOURCE_ACCOUNT_SEQUENCE);
644        assert_eq!(record.fee_account(), FEE_ACCOUNT);
645        assert_eq!(record.fee_charged(), FEE_CHARGED);
646        assert_eq!(record.max_fee(), MAX_FEE);
647        assert_eq!(record.operation_count(), OPERATION_COUNT);
648        assert_eq!(record.memo_type(), MEMO_TYPE);
649        assert_eq!(record.signatures()[0], SIGNATURE); // Check only the first signature of the vector
650        assert_eq!(record.valid_after().as_ref().unwrap(), VALID_AFTER);
651        assert_eq!(
652            record
653                .preconditions()
654                .as_ref()
655                .unwrap()
656                .timebounds()
657                .min_time(),
658            MIN_TIME
659        );
660    }
661}