From 5720f4b144fd7d7a3d7959f391a1cd92b2e3c550 Mon Sep 17 00:00:00 2001 From: Blaine Heffron Date: Tue, 23 Jul 2024 15:23:16 -0400 Subject: [PATCH] add getTransactions endpoint support (#3) * add getTransactions endpoint support --- Cargo.lock | 17 ++- Cargo.toml | 1 + src/fixtures/transactions_response.json | 63 ++++++++++++ src/lib.rs | 131 +++++++++++++++++++++++- 4 files changed, 206 insertions(+), 6 deletions(-) create mode 100644 src/fixtures/transactions_response.json diff --git a/Cargo.lock b/Cargo.lock index 2b4fe2f8..b03cad2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,6 +136,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "beef" version = "0.5.2" @@ -1007,11 +1013,11 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "chrono", "hex", "indexmap 1.9.3", @@ -1025,9 +1031,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.7.0" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ "darling", "proc-macro2", @@ -1084,6 +1090,7 @@ dependencies = [ "serde", "serde-aux", "serde_json", + "serde_with", "sha2", "stellar-strkey", "stellar-xdr", diff --git a/Cargo.toml b/Cargo.toml index 6cdf7853..958d73be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ itertools = "0.10.0" hex = "0.4.3" thiserror = "1.0.46" serde = "1.0.82" +serde_with = "3.9.0" tokio = "1.28.1" sha2 = "0.10.7" tracing = "0.1.40" diff --git a/src/fixtures/transactions_response.json b/src/fixtures/transactions_response.json new file mode 100644 index 00000000..ab274022 --- /dev/null +++ b/src/fixtures/transactions_response.json @@ -0,0 +1,63 @@ +{ + "jsonrpc": "2.0", + "id": 8675309, + "result": { + "transactions": [ + { + "status": "SUCCESS", + "applicationOrder": 1, + "feeBump": true, + "envelopeXdr": "AAAABQAAAABJY7yij5qHG5M7/ySeyr8JUnGtn+8EMCX4Xkc95+1XwAAAAAAAAFLaAAAAAgAAAAC7Ga10wMQS9VfQT5ecH6+WHJB9DOcNcB4jLTKUpCMJHAAAEGgABTQRAABIrAAAAAEAAAAAAAAAAAAAAABmlTKKAAAAAAAAAAQAAAABAAAAALsZrXTAxBL1V9BPl5wfr5YckH0M5w1wHiMtMpSkIwkcAAAAAwAAAAJHRUFHTEUAAAAAAAAAAAAAbzlnDJTtVGe6MKPrZ/1JITBhuKW2oynQUj0N3ARlRrAAAAABVVNEQwAAAADaHR1atgp7TAIbdfHYbujQdRgSedy7VIK08qqzOtl/JQAAAAAATEtAAMbcKQAAE4gAAAAAAAAvnAAAAAAAAAAMAAAAAVVTREMAAAAA2h0dWrYKe0wCG3Xx2G7o0HUYEnncu1SCtPKqszrZfyUAAAACR0VBR0xFAAAAAAAAAAAAAG85ZwyU7VRnujCj62f9SSEwYbiltqMp0FI9DdwEZUawAAAAAABMS0AAvw/DAAATiAAAAAAAADPtAAAAAQAAAAC7Ga10wMQS9VfQT5ecH6+WHJB9DOcNcB4jLTKUpCMJHAAAAAMAAAACU0VBR0xFAAAAAAAAAAAAAG85ZwyU7VRnujCj62f9SSEwYbiltqMp0FI9DdwEZUawAAAAAVVTREMAAAAA2h0dWrYKe0wCG3Xx2G7o0HUYEnncu1SCtPKqszrZfyUAAAAAAvrwgAABcScAAAnEAAAAAAAAM1oAAAAAAAAADAAAAAFVU0RDAAAAANodHVq2CntMAht18dhu6NB1GBJ53LtUgrTyqrM62X8lAAAAAlNFQUdMRQAAAAAAAAAAAABvOWcMlO1UZ7owo+tn/UkhMGG4pbajKdBSPQ3cBGVGsAAAAAAC+vCAAAFirQAACcQAAAAAAAAzXAAAAAAAAAABpCMJHAAAAEDiMjlDIA7TDfs4NslgQagfDd1Ju1WBi9p2sgBihb88gMbAMKhqxRrYsbT6fqStwb+G9Hd/5Jt10rTu4dS1PgsOAAAAAAAAAALn7VfAAAAAQCmEZYwcOjYJHQ+at97sniVUFR29zjKEU+gwTDluUgWIPKYMWlXckCvo/qlPyTrBT+mT4gQl52bTvtmGNfYiWQ+gr+RMAAAAQMzZWUUEW/BXwoP9pFCxwlbg1zCyJ6PLoyy2aMvJQ3v7uOMFwYTmNjEh3SUrKCMwI5+diLvhTtgGbMtTVhtTFAI=", + "resultXdr": "AAAAAAAAAfQAAAABt52fLaeY6MGab/VSMaCE9wfpwC35aNh8yY1dqgnrp08AAAAAAAABkAAAAAAAAAAEAAAAAAAAAAMAAAAAAAAAAAAAAAEAAAAAuxmtdMDEEvVX0E+XnB+vlhyQfQznDXAeIy0ylKQjCRwAAAAAAAAvnAAAAAJHRUFHTEUAAAAAAAAAAAAAbzlnDJTtVGe6MKPrZ/1JITBhuKW2oynQUj0N3ARlRrAAAAABVVNEQwAAAADaHR1atgp7TAIbdfHYbujQdRgSedy7VIK08qqzOtl/JQAAAAAATEtAAMbcKQAAE4gAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAABAAAAALsZrXTAxBL1V9BPl5wfr5YckH0M5w1wHiMtMpSkIwkcAAAAAAAAM+0AAAABVVNEQwAAAADaHR1atgp7TAIbdfHYbujQdRgSedy7VIK08qqzOtl/JQAAAAJHRUFHTEUAAAAAAAAAAAAAbzlnDJTtVGe6MKPrZ/1JITBhuKW2oynQUj0N3ARlRrAAAAAC6lWRuAAAE4gAvw/DAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAQAAAAC7Ga10wMQS9VfQT5ecH6+WHJB9DOcNcB4jLTKUpCMJHAAAAAAAADNaAAAAAlNFQUdMRQAAAAAAAAAAAABvOWcMlO1UZ7owo+tn/UkhMGG4pbajKdBSPQ3cBGVGsAAAAAFVU0RDAAAAANodHVq2CntMAht18dhu6NB1GBJ53LtUgrTyqrM62X8lAAAAAAL68IAAAXEnAAAJxAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAEAAAAAuxmtdMDEEvVX0E+XnB+vlhyQfQznDXAeIy0ylKQjCRwAAAAAAAAzXAAAAAFVU0RDAAAAANodHVq2CntMAht18dhu6NB1GBJ53LtUgrTyqrM62X8lAAAAAlNFQUdMRQAAAAAAAAAAAABvOWcMlO1UZ7owo+tn/UkhMGG4pbajKdBSPQ3cBGVGsAAAAABsPQugAAAJxAABYq0AAAAAAAAAAAAAAAAAAAAA", + "resultMetaXdr": "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", + "ledger": 554000, + "createdAt": 1721053660 + }, + { + "status": "FAILED", + "applicationOrder": 2, + "feeBump": true, + "envelopeXdr": "AAAABQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAHoSAAAAAAgAAAABakpti65/pchIY6MA9tdnvC+nOjez93jRTCt4EC1AG9wAAAAAAAbt0AAArLQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAMqbTGvyOcvPuApiT8JCDsMXqeRWck0Ss8Zlxc0OzhHAAAAAQAAAACbnSZIzRfeyiKP/2OZXM+VxMaDILZN2WR0cf3cJkrirgAAAAFVU0RDAAAAAEI+fQXy7K+/7BkrIVo/G+lq7bjY5wJUq+NBPgIH3layAAAAAAABhqAAAAAAAAAAAgtQBvcAAABA0NS7tsKA4/3vmmkLogq9ttmt7T9AI7DpKRYfRfK4GQG0jt0gt5TJ0MvvxRYqpbpJKly8i/AooOligli+S9gmDTQ7OEcAAABACRQ7yT6hIxqdKLEFj+7y/FqhfIH4hfeOIKvnMEHyvcTwsjZgsdWbYjZ2pdqo/nf6NaYhUBd5Js9AR9Gb6BztDwAAAAAAAAABNDs4RwAAAEBUlP5tJs/NYG49RpM0h9DmGUqu2J5IJwKVTHFblf6VLS4emA4BR20Z/7FvJfznsvRVLyjgmYV0TSxp/e1T7WkK", + "resultXdr": "AAAAAAAAAMj////z2kulXETbsMFgM3dKorDiBnr3dwty2Bjfns7uuiNocD4AAAAAAAAAAP////8AAAABAAAAAAAAAAH////7AAAAAAAAAAA=", + "resultMetaXdr": "AAAAAwAAAAAAAAAEAAAAAwAIdBAAAAAAAAAAAAMqbTGvyOcvPuApiT8JCDsMXqeRWck0Ss8Zlxc0OzhHAAAAF0dKM4gAAbsQAAAVaAAAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAEdAAAAAAAAAAMAAAAAAAc68wAAAABmjsTYAAAAAAAAAAEACHQQAAAAAAAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAABdHSjOIAAG7EAAAFWgAAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAABHQAAAAAAAAADAAAAAAAHOvMAAAAAZo7E2AAAAAAAAAADAAh0DQAAAAAAAAAAWpKbYuuf6XISGOjAPbXZ7wvpzo3s/d40UwreBAtQBvcAAAAAAAAAAAABu3QAACssAAAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAwAAAAAACHQNAAAAAGaVMc0AAAABAAAAAQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAAAABAAh0EAAAAAAAAAAAWpKbYuuf6XISGOjAPbXZ7wvpzo3s/d40UwreBAtQBvcAAAAAAAAAAAABu3QAACstAAAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAwAAAAAACHQQAAAAAGaVMdwAAAABAAAAAQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAAAAAAAAAAAAAAAA=", + "ledger": 554000, + "createdAt": 1721053660 + }, + { + "status": "FAILED", + "applicationOrder": 3, + "feeBump": false, + "envelopeXdr": "AAAAAgAAAACPMpUG2Y35WQpR+NuXcgRGJwHPFSb+EdNtFjkCn+tdnQAehIAAABp8AAFsjwAAAAEAAAAAAAAAAAAAAABmlTIXAAAAAQAAAAlwc3BiOjU3MjQAAAAAAAACAAAAAQAAAAC8gS/XWomLWgA83GQPIt1NvLv3eSldgrt3CUzNYWNTQAAAAAEAAAAAKENByUyEHMPiFKm6iyvXpA4Uxo222il18xT0gCIqxyAAAAACQVRTQlBJVVNEAAAAAAAAALyBL9daiYtaADzcZA8i3U28u/d5KV2Cu3cJTM1hY1NAAAAAAACaHSAAAAABAAAAALyBL9daiYtaADzcZA8i3U28u/d5KV2Cu3cJTM1hY1NAAAAAAQAAAABYdRrUzmvdMk3F+yPkOllnfTdWQV7chzw02Wom+5t0mwAAAAJBVFNCUElVU0QAAAAAAAAAvIEv11qJi1oAPNxkDyLdTby793kpXYK7dwlMzWFjU0AAAAAAAADDUAAAAAAAAAACn+tdnQAAAECIecdrBnSXzLxC/ldEyQ3jygQKAHw3kjZIUsvzhurtwb0WBG2ari0NHQN5AemzY7/zts+LXwhAe4gbsxpRBKgPYWNTQAAAAEDM6Jb4p0RfkBeub1xf6wQlI1VWhFmKUVO0mxiy/6ZVY7KrgohJK0eMlDUjtif5wbbwKx+6yfjdZPWlBkcnS78O", + "resultXdr": "AAAAAAAAAMj/////AAAAAgAAAAAAAAABAAAAAAAAAAAAAAAB////+gAAAAA=", + "resultMetaXdr": "AAAAAwAAAAAAAAACAAAAAwAIdBAAAAAAAAAAAI8ylQbZjflZClH425dyBEYnAc8VJv4R020WOQKf612dAAAAF0dlDuwAABp8AAFsjgAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAMAAAAAAAh0DAAAAABmlTHIAAAAAAAAAAEACHQQAAAAAAAAAACPMpUG2Y35WQpR+NuXcgRGJwHPFSb+EdNtFjkCn+tdnQAAABdHZQ7sAAAafAABbI8AAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAIdBAAAAAAZpUx3AAAAAAAAAAAAAAAAAAAAAA=", + "ledger": 554000, + "createdAt": 1721053660 + }, + { + "status": "FAILED", + "applicationOrder": 1, + "feeBump": true, + "envelopeXdr": "AAAABQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAHoSAAAAAAgAAAAA/D+vLzLHOzUZSH2x+hkCoCcxU1+sRrmi1noSXCPnBuQAAAAAAAbt3AAArOgAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAAAMqbTGvyOcvPuApiT8JCDsMXqeRWck0Ss8Zlxc0OzhHAAAAAQAAAACbnSZIzRfeyiKP/2OZXM+VxMaDILZN2WR0cf3cJkrirgAAAAFVU0RDAAAAAEI+fQXy7K+/7BkrIVo/G+lq7bjY5wJUq+NBPgIH3layAAAAAAABhqAAAAAAAAAAAgj5wbkAAABAgY6VYQ/F8z1p9BDtA/Cl5LnkWpHE/m97583K2BFaAXGIqCotp5YmcwqXK6Fik2DYpWkqDo/ERUYocHB/OkUkCjQ7OEcAAABAljpA6J/9uiz5JyZGaIH2LRZniRSFl3UqrS6vXPqX7L+i0hsLet+JZ4+d/XHnsHaPiX4XnX1b++dBkKnQlfKCDgAAAAAAAAABNDs4RwAAAECbNpACAYQa70RQ+wU5ZLyAKZ5rk4KQnBF/FSPkijTqsDLO7OnM98MAqgaPzHLiWnWRXmfgXjPkxG2NnEo6GjcJ", + "resultXdr": "AAAAAAAAAMj////z/xy6Zmx5GOhZNZ2cmjZU7DEt565puBlagNIxNVIrxTYAAAAAAAAAAP////8AAAABAAAAAAAAAAH////7AAAAAAAAAAA=", + "resultMetaXdr": "AAAAAwAAAAAAAAAEAAAAAwAIdBEAAAAAAAAAAAMqbTGvyOcvPuApiT8JCDsMXqeRWck0Ss8Zlxc0OzhHAAAAF0dKMsAAAbsQAAAVaAAAAAEAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAEdAAAAAAAAAAMAAAAAAAc68wAAAABmjsTYAAAAAAAAAAEACHQRAAAAAAAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAABdHSjLAAAG7EAAAFWgAAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAABHQAAAAAAAAADAAAAAAAHOvMAAAAAZo7E2AAAAAAAAAADAAh0DgAAAAAAAAAAPw/ry8yxzs1GUh9sfoZAqAnMVNfrEa5otZ6Elwj5wbkAAAAAAAAAAAABu3cAACs5AAAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAwAAAAAACHQOAAAAAGaVMdIAAAABAAAAAQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAAAABAAh0EQAAAAAAAAAAPw/ry8yxzs1GUh9sfoZAqAnMVNfrEa5otZ6Elwj5wbkAAAAAAAAAAAABu3cAACs6AAAAAQAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAwAAAAAAAAAAAAAAAwAAAAAACHQRAAAAAGaVMeEAAAABAAAAAQAAAAADKm0xr8jnLz7gKYk/CQg7DF6nkVnJNErPGZcXNDs4RwAAAAAAAAAAAAAAAAAAAAA=", + "ledger": 554001, + "createdAt": 1721053665 + }, + { + "status": "FAILED", + "applicationOrder": 1, + "feeBump": false, + "envelopeXdr": "AAAAAgAAAAD9uf1CchADZI+J66kA1h8K4eSH8If09/pmH3FEgmtXHQAPQkAABOqMAAAAQQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAAABB90WssODNIgi6BHveqzxTRmIpvAFRyVNM+Hm2GVuCcAAAAAAAAAAAoPal+zKptoJOJ8qXgtzOK7QIgGaywZi+rbUXxGdP8IQAAABdIdugAAAAAAAAAAAKCa1cdAAAAQLO2Wz1eHe5f9axdfVH9zsoxsK9Ay2q/szum9CDh+JAohXXSe0zaJJ9jesv8Fsbel5S9eGPTfEMXn6TDO/YtTQKGVuCcAAAAQEtWH9n07F06uyX7JZxry5RCKu+2qDpuMxkmIXBhA4KoOuz0Q5z5+05ise14KO/3t7mDVXVmLNTUpJxj0l3S5gM=", + "resultXdr": "AAAAAAAAAGT/////AAAAAQAAAAAAAAAA/////AAAAAA=", + "resultMetaXdr": "AAAAAwAAAAAAAAACAAAAAwAIdBIAAAAAAAAAAP25/UJyEANkj4nrqQDWHwrh5Ifwh/T3+mYfcUSCa1cdAAAAADwzRxwABOqMAAAAQAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAMAAAAAAAhwQgAAAABmlR3OAAAAAAAAAAEACHQSAAAAAAAAAAD9uf1CchADZI+J66kA1h8K4eSH8If09/pmH3FEgmtXHQAAAAA8M0ccAATqjAAAAEEAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAADAAAAAAAIdBIAAAAAZpUx5gAAAAAAAAAAAAAAAAAAAAA=", + "ledger": 554002, + "createdAt": 1721053670 + } + ], + "latestLedger": 556962, + "latestLedgerCloseTimestamp": 1721069238, + "oldestLedger": 539683, + "oldestLedgerCloseTimestamp": 1720978478, + "cursor": "2379420471922689" + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 799e5a00..a8133afb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ use serde_aux::prelude::{ deserialize_default_from_null, deserialize_number_from_string, deserialize_option_number_from_string, }; +use serde_with::{serde_as, DisplayFromStr}; use stellar_xdr::curr::{ self as xdr, AccountEntry, AccountId, ContractDataEntry, ContractEventType, DiagnosticEvent, Error as XdrError, Hash, LedgerEntryData, LedgerFootprint, LedgerKey, LedgerKeyAccount, @@ -99,7 +100,6 @@ pub enum Error { LargeFee(u64), #[error("Cannot authorize raw transactions")] CannotAuthorizeRawTransaction, - #[error("Missing result for tnx")] MissingOp, } @@ -208,6 +208,66 @@ impl GetTransactionResponse { } } +#[serde_as] +#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)] +pub struct GetTransactionsResponseRaw { + pub transactions: Vec, + #[serde(rename = "latestLedger")] + pub latest_ledger: u32, + #[serde(rename = "latestLedgerCloseTimestamp")] + pub latest_ledger_close_time: i64, + #[serde(rename = "oldestLedger")] + pub oldest_ledger: u32, + #[serde(rename = "oldestLedgerCloseTimestamp")] + pub oldest_ledger_close_time: i64, + #[serde_as(as = "DisplayFromStr")] + pub cursor: u64, +} +#[derive(serde::Deserialize, serde::Serialize, Debug, Clone)] +pub struct GetTransactionsResponse { + pub transactions: Vec, + pub latest_ledger: u32, + pub latest_ledger_close_time: i64, + pub oldest_ledger: u32, + pub oldest_ledger_close_time: i64, + pub cursor: u64, +} +impl TryInto for GetTransactionsResponseRaw { + type Error = xdr::Error; // assuming xdr::Error or any other error type that you use + + fn try_into(self) -> Result { + Ok(GetTransactionsResponse { + transactions: self + .transactions + .into_iter() + .map(TryInto::try_into) + .collect::, xdr::Error>>()?, + latest_ledger: self.latest_ledger, + latest_ledger_close_time: self.latest_ledger_close_time, + oldest_ledger: self.oldest_ledger, + oldest_ledger_close_time: self.oldest_ledger_close_time, + cursor: self.cursor, + }) + } +} + +#[serde_as] +#[derive(serde::Serialize, Debug, Clone)] +pub struct TransactionsPaginationOptions { + #[serde_as(as = "Option")] + #[serde(skip_serializing_if = "Option::is_none")] + pub cursor: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub limit: Option, +} + +#[derive(serde::Serialize, Debug, Clone)] +pub struct GetTransactionsRequest { + #[serde(skip_serializing_if = "Option::is_none")] + pub start_ledger: Option, + pub pagination: Option, +} + #[derive(serde::Deserialize, serde::Serialize, Debug, Clone)] pub struct LedgerEntryResult { pub key: String, @@ -807,6 +867,25 @@ impl Client { Ok(resp.try_into()?) } + /// + /// # Errors + pub async fn get_transactions( + &self, + request: GetTransactionsRequest, + ) -> Result { + let mut oparams = ObjectParams::new(); + if let Some(start_ledger) = request.start_ledger { + oparams.insert("startLedger", start_ledger)?; + } + if let Some(pagination_params) = request.pagination { + let pagination = serde_json::json!(pagination_params); + oparams.insert("pagination", pagination)?; + } + let resp: GetTransactionsResponseRaw = + self.client().request("getTransactions", oparams).await?; + Ok(resp.try_into()?) + } + /// Poll the transaction status. Can provide a timeout in seconds, otherwise uses the default timeout. /// /// It uses exponential backoff with a base of 1 second and a maximum of 30 seconds. @@ -1070,6 +1149,9 @@ pub(crate) fn parse_cursor(c: &str) -> Result<(u64, i32), Error> { #[cfg(test)] mod tests { use super::*; + use std::env; + use std::fs; + use std::path::PathBuf; #[test] fn simulation_transaction_response_parsing() { @@ -1104,6 +1186,53 @@ mod tests { assert_eq!(resp.latest_ledger, 1_234); } + fn get_repo_root() -> PathBuf { + let mut path = env::current_exe().expect("Failed to get current executable path"); + // Navigate up the directory tree until we find the repository root + while path.pop() { + if path.join("Cargo.toml").exists() { + return path; + } + } + panic!("Could not find repository root"); + } + + #[test] + fn test_parse_get_transactions_response() { + let repo_root = get_repo_root(); + let fixture_path = repo_root + .join("src") + .join("fixtures") + .join("transactions_response.json"); + let response_content = + fs::read_to_string(fixture_path).expect("Failed to read transactions_response.json"); + + // Parse the entire response + let full_response: serde_json::Value = serde_json::from_str(&response_content) + .expect("Failed to parse JSON from transactions_response.json"); + + // Extract the "result" field + let result = full_response["result"].clone(); + // Parse the "result" content as GetTransactionsResponseRaw + let raw_response: GetTransactionsResponseRaw = serde_json::from_value(result) + .expect("Failed to parse 'result' into GetTransactionsResponseRaw"); + + // Convert GetTransactionsResponseRaw to GetTransactionsResponse + let response: GetTransactionsResponse = raw_response + .try_into() + .expect("Failed to convert GetTransactionsResponseRaw to GetTransactionsResponse"); + + // Assertions + assert_eq!(response.transactions.len(), 5); + assert_eq!(response.latest_ledger, 556_962); + assert_eq!(response.cursor, 2_379_420_471_922_689); + + // Additional assertions for specific transaction attributes + assert_eq!(response.transactions[0].status, "SUCCESS"); + //assert_eq!(response.transactions[0].application_order, 1); + //assert_eq!(response.transactions[0].ledger, 554000); + } + #[test] fn test_rpc_url_default_ports() { // Default ports are added.