fix: pagination for all completed transactions gRPC method#7366
Conversation
WalkthroughThis change introduces a new streaming gRPC method for retrieving completed wallet transactions with database-backed pagination and optional status filtering. The server, service, and storage layers are extended to support paginated queries, and the previous non-streaming method is marked as deprecated. Proto definitions, server logic, and database access are updated accordingly. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant WalletGrpcServer
participant TransactionServiceHandle
participant TransactionService
participant Database
Client->>WalletGrpcServer: GetAllCompletedTransactionsStream(request)
loop while more transactions
WalletGrpcServer->>TransactionServiceHandle: get_completed_transactions_paginated(offset, limit, status_filter)
TransactionServiceHandle->>TransactionService: GetCompletedTransactionsPaginated(offset, limit, status_filter)
TransactionService->>Database: get_completed_transactions_paginated(offset, limit, status_filter)
Database-->>TransactionService: Vec<CompletedTransaction>
TransactionService-->>TransactionServiceHandle: Vec<CompletedTransaction>
TransactionServiceHandle-->>WalletGrpcServer: Vec<CompletedTransaction>
WalletGrpcServer-->>Client: stream GetCompletedTransactionsResponse (chunk)
end
Estimated code review effort4 (~90 minutes) Possibly related PRs
Suggested reviewers
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🧠 Learnings (2)📓 Common learningsbase_layer/wallet/src/transaction_service/error.rs (1)Learnt from: hansieodendaal 🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used🧠 Learnings (2)📓 Common learningsbase_layer/wallet/src/transaction_service/error.rs (1)Learnt from: hansieodendaal ⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
🔇 Additional comments (1)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
base_layer/wallet/src/transaction_service/service.rs (1)
1008-1015: LGTM! Implementation follows established patterns.The new
GetCompletedTransactionsPaginatedrequest handler is correctly implemented and follows the same pattern as other request handlers in this method. The parameters are properly passed through to the database layer and the response is correctly wrapped.However, consider adding input validation for the pagination parameters:
TransactionServiceRequest::GetCompletedTransactionsPaginated { offset, limit, status_filter, -} => Ok(TransactionServiceResponse::CompletedTransactions( - self.db - .get_completed_transactions_paginated(offset, limit, status_filter)?, -)), +} => { + // Validate pagination parameters + if limit == 0 { + return Err(TransactionServiceError::InvalidArgument("limit must be greater than 0".to_string())); + } + Ok(TransactionServiceResponse::CompletedTransactions( + self.db + .get_completed_transactions_paginated(offset, limit, status_filter)?, + )) +},base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (1)
1277-1281: Consider adding performance monitoring.Following the pattern established in other methods in this file, consider adding performance monitoring to track query execution time, especially since this method will be used for streaming operations that may be called frequently.
+ let start = Instant::now(); let mut conn = self.database_connection.get_pooled_connection()?; + let acquire_lock = start.elapsed(); let cipher = acquire_read_lock!(self.cipher); use diesel::prelude::*; // ... existing query logic ... - query + let result = query .order(completed_transactions::timestamp.desc()) .offset(offset as i64) .limit(limit as i64) .load::<CompletedTransactionSql>(&mut conn)? .into_iter() .map(|ct: CompletedTransactionSql| { CompletedTransaction::try_from(ct, &cipher).map_err(TransactionStorageError::from) }) - .collect::<Result<Vec<CompletedTransaction>, TransactionStorageError>>() + .collect::<Result<Vec<CompletedTransaction>, TransactionStorageError>>()?; + + if start.elapsed().as_millis() > 0 { + trace!( + target: LOG_TARGET, + "sqlite profile - find_completed_transactions_paginated: lock {} + db_op {} = {} ms", + acquire_lock.as_millis(), + (start.elapsed() - acquire_lock).as_millis(), + start.elapsed().as_millis() + ); + } + + Ok(result)applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (1)
1280-1407: Good refactoring with chunked pagination.The implementation correctly handles pagination and adds a deprecation warning. The chunked approach with a maximum of 100 items per chunk is a good balance for memory efficiency.
Consider documenting the chunk size choice (100) with a comment explaining the rationale.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
applications/minotari_app_grpc/proto/wallet.proto(2 hunks)applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs(5 hunks)base_layer/wallet/src/transaction_service/handle.rs(3 hunks)base_layer/wallet/src/transaction_service/service.rs(1 hunks)base_layer/wallet/src/transaction_service/storage/database.rs(2 hunks)base_layer/wallet/src/transaction_service/storage/sqlite_db.rs(1 hunks)
🧠 Learnings (7)
📓 Common learnings
Learnt from: hansieodendaal
PR: tari-project/tari#6963
File: comms/core/src/peer_manager/manager.rs:60-68
Timestamp: 2025-05-26T02:40:23.812Z
Learning: PeerDatabaseSql in the Tari codebase has been specifically refactored to handle concurrent access and mitigate blocking I/O concerns on async executor threads. The implementation has been tested under high load at both system level and through unit tests like test_concurrent_add_or_update_and_get_closest_peers which validates concurrent read/write operations.
base_layer/wallet/src/transaction_service/handle.rs (2)
Learnt from: ksrichard
PR: #7129
File: applications/minotari_node/src/http/handler/sync_utxos_by_block.rs:21-29
Timestamp: 2025-05-29T20:59:32.020Z
Learning: In the Tari codebase, request validation for RPC services is handled at the service layer using the serde_valid crate rather than at the HTTP handler level. For example, SyncUtxosByBlockRequest validates that limit is between 1-5 and page is minimum 0. HTTP handlers should delegate validation to the service layer rather than implementing their own validation.
Learnt from: hansieodendaal
PR: #7284
File: applications/minotari_console_wallet/src/automation/commands.rs:0-0
Timestamp: 2025-07-15T12:23:14.650Z
Learning: In applications/minotari_console_wallet/src/automation/commands.rs, the consistent error handling pattern for command execution is to use match statements that: 1) On success: log with debug!, print user feedback, and push tx_id to tx_ids vector for monitoring, 2) On error: print error message with eprintln! using the format "{CommandName} error! {}", rather than using .unwrap() which would panic.
base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (1)
Learnt from: hansieodendaal
PR: #7123
File: comms/core/src/peer_manager/storage/database.rs:1517-1541
Timestamp: 2025-05-29T09:42:20.881Z
Learning: In the hard_delete_all_stale_peers method in comms/core/src/peer_manager/storage/database.rs, the SQL query intentionally uses exact equality (peers.features = ?) rather than bitwise operations (peers.features & ? != 0) when matching COMMUNICATION_NODE features. This is the intended behavior to match only peers with exactly the COMMUNICATION_NODE feature, excluding those with additional feature flags.
applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (4)
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy. The wallet.proto file confirms that timelocked_balance is defined as the fourth field in the GetBalanceResponse message.
Learnt from: hansieodendaal
PR: #7284
File: applications/minotari_console_wallet/src/automation/commands.rs:0-0
Timestamp: 2025-07-15T12:23:14.650Z
Learning: In applications/minotari_console_wallet/src/automation/commands.rs, the consistent error handling pattern for command execution is to use match statements that: 1) On success: log with debug!, print user feedback, and push tx_id to tx_ids vector for monitoring, 2) On error: print error message with eprintln! using the format "{CommandName} error! {}", rather than using .unwrap() which would panic.
Learnt from: hansieodendaal
PR: #7294
File: comms/dht/src/network_discovery/seed_strap.rs:352-456
Timestamp: 2025-07-09T08:33:29.320Z
Learning: In comms/dht/src/network_discovery/seed_strap.rs, the fetch_peers_from_connection and collect_peer_stream functions rely on RPC streaming, and when the main connection is closed by another process, collect_peer_stream times out after STREAM_ITEM_TIMEOUT because it cannot detect that the peer can no longer respond, returning an empty vector of peers. This is why the connection state check is important for the retry logic.
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy.
base_layer/wallet/src/transaction_service/storage/database.rs (1)
Learnt from: SWvheerden
PR: #7300
File: base_layer/wallet/src/transaction_service/service.rs:1663-1663
Timestamp: 2025-07-10T13:21:46.666Z
Learning: In the Tari wallet codebase, scanned height persistence is handled by the UTXO scanner service, not individual services like TransactionService. Services that need current scanned height should read it via get_last_scanned_height() rather than persisting it themselves. This follows separation of concerns architecture pattern.
applications/minotari_app_grpc/proto/wallet.proto (2)
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy. The wallet.proto file confirms that timelocked_balance is defined as the fourth field in the GetBalanceResponse message.
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy.
base_layer/wallet/src/transaction_service/service.rs (1)
Learnt from: ksrichard
PR: #7129
File: applications/minotari_node/src/http/handler/sync_utxos_by_block.rs:21-29
Timestamp: 2025-05-29T20:59:32.020Z
Learning: In the Tari codebase, request validation for RPC services is handled at the service layer using the serde_valid crate rather than at the HTTP handler level. For example, SyncUtxosByBlockRequest validates that limit is between 1-5 and page is minimum 0. HTTP handlers should delegate validation to the service layer rather than implementing their own validation.
🧰 Additional context used
🧠 Learnings (7)
📓 Common learnings
Learnt from: hansieodendaal
PR: tari-project/tari#6963
File: comms/core/src/peer_manager/manager.rs:60-68
Timestamp: 2025-05-26T02:40:23.812Z
Learning: PeerDatabaseSql in the Tari codebase has been specifically refactored to handle concurrent access and mitigate blocking I/O concerns on async executor threads. The implementation has been tested under high load at both system level and through unit tests like test_concurrent_add_or_update_and_get_closest_peers which validates concurrent read/write operations.
base_layer/wallet/src/transaction_service/handle.rs (2)
Learnt from: ksrichard
PR: #7129
File: applications/minotari_node/src/http/handler/sync_utxos_by_block.rs:21-29
Timestamp: 2025-05-29T20:59:32.020Z
Learning: In the Tari codebase, request validation for RPC services is handled at the service layer using the serde_valid crate rather than at the HTTP handler level. For example, SyncUtxosByBlockRequest validates that limit is between 1-5 and page is minimum 0. HTTP handlers should delegate validation to the service layer rather than implementing their own validation.
Learnt from: hansieodendaal
PR: #7284
File: applications/minotari_console_wallet/src/automation/commands.rs:0-0
Timestamp: 2025-07-15T12:23:14.650Z
Learning: In applications/minotari_console_wallet/src/automation/commands.rs, the consistent error handling pattern for command execution is to use match statements that: 1) On success: log with debug!, print user feedback, and push tx_id to tx_ids vector for monitoring, 2) On error: print error message with eprintln! using the format "{CommandName} error! {}", rather than using .unwrap() which would panic.
base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (1)
Learnt from: hansieodendaal
PR: #7123
File: comms/core/src/peer_manager/storage/database.rs:1517-1541
Timestamp: 2025-05-29T09:42:20.881Z
Learning: In the hard_delete_all_stale_peers method in comms/core/src/peer_manager/storage/database.rs, the SQL query intentionally uses exact equality (peers.features = ?) rather than bitwise operations (peers.features & ? != 0) when matching COMMUNICATION_NODE features. This is the intended behavior to match only peers with exactly the COMMUNICATION_NODE feature, excluding those with additional feature flags.
applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (4)
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy. The wallet.proto file confirms that timelocked_balance is defined as the fourth field in the GetBalanceResponse message.
Learnt from: hansieodendaal
PR: #7284
File: applications/minotari_console_wallet/src/automation/commands.rs:0-0
Timestamp: 2025-07-15T12:23:14.650Z
Learning: In applications/minotari_console_wallet/src/automation/commands.rs, the consistent error handling pattern for command execution is to use match statements that: 1) On success: log with debug!, print user feedback, and push tx_id to tx_ids vector for monitoring, 2) On error: print error message with eprintln! using the format "{CommandName} error! {}", rather than using .unwrap() which would panic.
Learnt from: hansieodendaal
PR: #7294
File: comms/dht/src/network_discovery/seed_strap.rs:352-456
Timestamp: 2025-07-09T08:33:29.320Z
Learning: In comms/dht/src/network_discovery/seed_strap.rs, the fetch_peers_from_connection and collect_peer_stream functions rely on RPC streaming, and when the main connection is closed by another process, collect_peer_stream times out after STREAM_ITEM_TIMEOUT because it cannot detect that the peer can no longer respond, returning an empty vector of peers. This is why the connection state check is important for the retry logic.
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy.
base_layer/wallet/src/transaction_service/storage/database.rs (1)
Learnt from: SWvheerden
PR: #7300
File: base_layer/wallet/src/transaction_service/service.rs:1663-1663
Timestamp: 2025-07-10T13:21:46.666Z
Learning: In the Tari wallet codebase, scanned height persistence is handled by the UTXO scanner service, not individual services like TransactionService. Services that need current scanned height should read it via get_last_scanned_height() rather than persisting it themselves. This follows separation of concerns architecture pattern.
applications/minotari_app_grpc/proto/wallet.proto (2)
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy. The wallet.proto file confirms that timelocked_balance is defined as the fourth field in the GetBalanceResponse message.
Learnt from: SolfataraEmit
PR: #6994
File: docs/src/API_GRPC_Explanation.md:236-244
Timestamp: 2025-04-28T11:41:15.722Z
Learning: The minotari_console_wallet reports a fourth field timelocked_balance in the terminal output for the getBalance method, which should be reflected in the documentation for accuracy.
base_layer/wallet/src/transaction_service/service.rs (1)
Learnt from: ksrichard
PR: #7129
File: applications/minotari_node/src/http/handler/sync_utxos_by_block.rs:21-29
Timestamp: 2025-05-29T20:59:32.020Z
Learning: In the Tari codebase, request validation for RPC services is handled at the service layer using the serde_valid crate rather than at the HTTP handler level. For example, SyncUtxosByBlockRequest validates that limit is between 1-5 and page is minimum 0. HTTP handlers should delegate validation to the service layer rather than implementing their own validation.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: ledger build tests
- GitHub Check: test (mainnet, stagenet)
- GitHub Check: test (testnet, esmeralda)
- GitHub Check: cargo check with stable
- GitHub Check: test (nextnet, nextnet)
- GitHub Check: ci
🔇 Additional comments (13)
base_layer/wallet/src/transaction_service/storage/database.rs (2)
176-181: Well-designed trait method for paginated queries.The method signature is consistent with existing trait methods and properly designed for database-backed pagination with optional status filtering.
878-886: LGTM! Consistent wrapper implementation.The method follows the established pattern of other database wrapper methods and properly delegates to the backend implementation.
base_layer/wallet/src/transaction_service/handle.rs (3)
95-99: Well-structured enum variant for paginated requests.The variant follows established naming conventions and parameter patterns, with types that properly match the corresponding database method.
279-279: Consistent display implementation.The display implementation follows the established pattern of other enum variants in the trait.
1269-1287: Properly implemented handle method.The method follows the established pattern of other handle methods with correct async implementation, error handling, and response type matching.
base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (2)
1250-1252: Add input validation for pagination parameters.The method should validate that
offsetandlimitparameters are within reasonable bounds to prevent potential performance issues or resource exhaustion.+ // Validate pagination parameters + const MAX_LIMIT: u64 = 10_000; // Define reasonable maximum + if limit == 0 || limit > MAX_LIMIT { + return Err(TransactionStorageError::InvalidArgument( + format!("Limit must be between 1 and {}", MAX_LIMIT) + )); + } + let mut conn = self.database_connection.get_pooled_connection()?;⛔ Skipped due to learnings
Learnt from: ksrichard PR: tari-project/tari#7129 File: applications/minotari_node/src/http/handler/sync_utxos_by_block.rs:21-29 Timestamp: 2025-05-29T20:59:32.020Z Learning: In the Tari codebase, request validation for RPC services is handled at the service layer using the `serde_valid` crate rather than at the HTTP handler level. For example, `SyncUtxosByBlockRequest` validates that limit is between 1-5 and page is minimum 0. HTTP handlers should delegate validation to the service layer rather than implementing their own validation.
1245-1287: Bitflag-to-status mapping is correct; no changes neededVerified that the
TransactionStatusenum discriminants are defined as sequential integers (Completed = 0, Broadcast = 1, … OneSidedUnconfirmed = 8), so mapping bit position i → status value i is accurate. The current loop over 0..32 correctly builds the list of status codes.Using
trailing_zeros()to iterate only set bits is a valid micro-optimization but not required here. No fixes are necessary.Likely an incorrect or invalid review comment.
applications/minotari_app_grpc/proto/wallet.proto (2)
1804-1809: Clarify & enforcelimitsemantics.
- The comment’s grammar is unclear (“limited to 50 if passed higher number than it will be reduced to 50”).
- Nothing in the proto enforces the cap; the server must clamp it.
Consider tightening both documentation and validation:
- // limited to 50 if passed higher number than it will be reduced to 50 + // Maximum page size. Values > 50 will be clamped to 50 by the server.Optionally, expose the max as a constant in the service docs or an enum so clients don’t hard-code
50.Ensure the backend handler actually clamps the value; otherwise the proto comment becomes misleading.
1811-1814: Also deprecate the response message.
GetAllCompletedTransactionsResponseis now only used by the deprecated RPC.
Marking the message itself as deprecated prevents accidental reuse and triggers compiler warnings.-message GetAllCompletedTransactionsResponse { - repeated TransactionInfo transactions = 1; -} +message GetAllCompletedTransactionsResponse { + option deprecated = true; + repeated TransactionInfo transactions = 1; +}[ suggest_optional_refactor ]
applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (4)
242-242: LGTM!The new associated type follows the established naming convention and pattern for streaming responses.
1146-1147: Good catch on the log message correction.The updated log message now correctly reflects the method name.
1185-1186: Consistent log message updates.All log messages have been correctly updated to match the method name.
Also applies to: 1256-1260
1409-1610: Excellent streaming implementation.The new streaming method is well-designed with:
- Appropriate chunk size (50) for responsive streaming
- Comprehensive error handling that sends errors to the client
- Graceful handling of client disconnection
- Detailed logging at appropriate levels
- Defensive programming with
saturating_subThe implementation provides better memory efficiency and responsiveness compared to the batch method.
| // Get all completed transactions including cancelled ones, sorted by timestamp and paginated | ||
| // DEPRECATED: Use GetAllCompletedTransactionsStream for better performance and memory efficiency | ||
| rpc GetAllCompletedTransactions(GetAllCompletedTransactionsRequest) returns (GetAllCompletedTransactionsResponse); | ||
|
|
||
| // Get all completed transactions including cancelled ones, sorted by timestamp and paginated (streaming version) | ||
| // Recommended: Use this streaming version for better performance and progressive loading | ||
| rpc GetAllCompletedTransactionsStream(GetAllCompletedTransactionsRequest) returns (stream GetCompletedTransactionsResponse); | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Mark the unary RPC as formally deprecated and add explicit options on both RPCs.
You rely on a comment to signal deprecation, but the proto spec already provides option deprecated = true; on an RPC MethodOptions.
This makes the deprecation machine-readable for code-gen (Rust, Go, Java, TS-grpc, etc.) and raises compile-time warnings rather than relying on humans to read comments.
- // DEPRECATED: Use GetAllCompletedTransactionsStream for better performance and memory efficiency
- rpc GetAllCompletedTransactions(GetAllCompletedTransactionsRequest)
- returns (GetAllCompletedTransactionsResponse);
+ rpc GetAllCompletedTransactions(GetAllCompletedTransactionsRequest)
+ returns (GetAllCompletedTransactionsResponse) {
+ option deprecated = true; // machine-readable
+ }
- // Get all completed transactions including cancelled ones, sorted by timestamp and paginated (streaming version)
- // Recommended: Use this streaming version for better performance and progressive loading
- rpc GetAllCompletedTransactionsStream(GetAllCompletedTransactionsRequest) returns (stream GetCompletedTransactionsResponse);
+ // Streaming version – preferred for pagination + memory efficiency.
+ rpc GetAllCompletedTransactionsStream(GetAllCompletedTransactionsRequest)
+ returns (stream GetCompletedTransactionsResponse);This tiny change improves DX across every generated client.
(No functional impact on the wire.)
🤖 Prompt for AI Agents
In applications/minotari_app_grpc/proto/wallet.proto around lines 1102 to 1109,
the unary RPC GetAllCompletedTransactions is marked as deprecated only via
comments. To fix this, add the option deprecated = true; to its RPC method
options to formally mark it as deprecated in the proto spec. Also, add explicit
options (such as idempotency level or other relevant options) to both
GetAllCompletedTransactions and GetAllCompletedTransactionsStream RPCs to
improve clarity and support for code generation tools. This change will enable
machine-readable deprecation and better developer experience without affecting
runtime behavior.
Description
Closes: #7274
Adds new methods
GetAllCompletedTransactionsStreamwhich fixes pagination and deprecatesGetAllCompletedTransactions.This PR changes query for all completed transaction to utilize SQL
LIMITandOFFSETinstead of filtering it in memory and also returns data as stream instead as a single response.How Has This Been Tested?
Run
cargo checkand tests to verify every check is passed.Use 3rd party tool like
grpcurlto check method response:Breaking Changes
Summary by CodeRabbit
New Features
Improvements
Bug Fixes