Conversation
|
This sort of API was talked about in bdk_wallet#100 and scoped down to tx_details in #201 But I'm not sure if the N+1 FFI roundtrip cost you're describing was discussed? Mostly just adding a comment here just to add some additional context. Definitely understand why its useful/valuable. |
|
@reez Thanks for the context, i actually searched for such but couldn't find. bdk_wallet#100 identified the same underlying composition problem but FFI roundtrip was not factored, this PR is actually motivated by that cost when those APIs are consumed through FFI (serd) + developer ergonomics. |
|
|
||
| txids | ||
| .into_iter() | ||
| .filter_map(|txid| wallet.tx_details(txid)) |
There was a problem hiding this comment.
Could we avoid calling wallet.tx_details() once per txid here? In bdk_wallet 3.1.0, tx_details() scans self.transactions() to locate each transaction, so this repeatedly scans the full history and makes the bulk API O(n²). Since this method targets transaction-history performance, could we derive details from the already-fetched WalletTxs or expose an upstream bulk API?
There was a problem hiding this comment.
Hi @j-kon thanks for pointing that out, let me look into it.
|
Hi @j-kon. I tried restructuring the all_tx_details method to derive the details directly from the already-fetched WalletTxs like this: `pub fn all_tx_details(&self) -> Veccrate::types::TxDetails { }` But I'm not sure if the balance_delta workaround calculation above is ok to use. In bdk_wallet 3.1.0, tx_details() derives it from: And given that bdk_wallet#100 discussion is scoped down to tx_details. My understanding is that adding an all_tx_details() API directly to bdk_wallet would probably be easier. but it would not fit the goal of keeping the bdk_wallet API composable and application-independent as per bdk_wallet#100. The blocker I'm hitting is the transaction-graph-derived balance_delta. So should we adopt this method or is there an existing public API in bdk_wallet/bdk_chain that can calculate the same balance_delta from an already-fetched WalletTx, or a supported way for the FFI crate to access the relevant transaction graph/index without relying on private Wallet internals? |
|
let balance_delta = received.to_signed().expect("valid SignedAmount")
- sent.to_signed().expect("valid SignedAmount");This direct construction looks reasonable for avoiding the repeated transaction scans. Please also update the test to use a funded wallet and compare the resulting fields and ordering against |
Description
Wallet currently exposes two methods for querying transactions:
transactions(&self) -> Vec: Returns all canonical transactions, but only provides basic information (txid, chain position, raw transaction). It lacks rich metadata such as fee, fee_rate, sent, received, and balance_delta.
tx_details(&self, txid: Arc) -> Option: Returns rich transaction details, but only for a single transaction at a time.
When building user interfaces like a transaction history screen in foreign language bindings (e.g. Dart), consumers are forced into an N+1 FFI round-trips for every transaction, this creates unnecessary overhead across language boundaries and inflates boilerplate in down-stream bindings.
all_tx_details()does this in a single call from the caller's perspective.Notes to the reviewers
If maintainers are aligned with this approach, I would be happy to add tests and docs.
Additional implementation finding
While implementing the this API, it was found that it only solve first part of the performance issue. The original Rust-side approach of calling wallet.tx_details() once per transaction also introduces repeated transaction-history scans.
In bdk_wallet 3.1.0, Wallet::tx_details(txid) locates the requested transaction by scanning self.transactions()
This means the optimization has two dimensions:
The implementation now derives TxDetails directly from the already-fetched WalletTx values returned by transactions_sort_by() without performing the repeated lookup.
Documentation
bdk_walletbitcoinuniffiChangelog
Checklists
All Submissions:
cargo fmtandcargo clippybefore committingchangelog:*labelNew Features:
Bugfixes: