Adds non-mempool wallet balance to overview #952

pull polespinasa wants to merge 6 commits into bitcoin-core:master from polespinasa:2026-07-27-wallet_nonmempool_balance changing 6 files +67 −10
  1. polespinasa commented at 3:21 PM on July 27, 2026: member

    Just grabbing #911

    Copying the motivation from AJ's description:

    The wallet can contain transactions that are not accepted into the node's mempool (eg due to containing a too large OP_RETURN output, due to too low a feerate, or due to too many unconfirmed ancestors). In the event you end up in this situation, it can appear as if funds have gone missing from your wallet due to the non-mempool balance not being reported. Correct this by reporting the non-mempool balance.

    See https://github.com/bitcoin/bitcoin/pull/33671 for further context.

    The changes look like:

    <img width="372" height="239" alt="imagen" src="https://github.com/user-attachments/assets/2adab476-0db1-4354-9e51-ddddca26c61a" />

    How to test

    To test, start with -datacarriersize=10, and run

    send '{"data": "4368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73"}' null "unset" 1
    

    from the console. "Non-mempool: <change amount>" should appear in the Balances pane on the Overview window with the change from the transaction. Restarting with -datacarriersize=100000 should allow the tx to enter the mempool, and move the amount into the Available balance. (Presumably, do this on -regtest after generating 100 blocks; or perhaps signet after grabbing some funds from a faucet)

  2. DrahtBot commented at 3:21 PM on July 27, 2026: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--021abf342d371248e50ceaed478a90ca-->

    Reviews

    See the guideline and AI policy for information on the review process.

    Type Reviewers
    Stale ACK pablomartin4btc

    If your review is incorrectly listed, please copy-paste <code>&lt;!--meta-tag:bot-skip--&gt;</code> into the comment that the bot should ignore.

    <!--5faf32d7da4f0f540f40219e4f7537a3-->

  3. gui: remove the unecessary padding before - and + signs 2fc1e2c16e
  4. wallet, test: Include nonmempool balance in getBalances interface
    Use getBalances when testing the current balance in OverviewPage to take into account
    non_mempool balances in next commits.
    
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    34d02abc83
  5. qt: remove assert in formatWithPrivacy
    The assert removal is necesary for a next commit to introduce nonmempoolbalance
    as that balance should always be negative thus making this assert no longer true.
    
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    e7585d0c63
  6. polespinasa force-pushed on Jul 27, 2026
  7. DrahtBot added the label CI failed on Jul 27, 2026
  8. DrahtBot commented at 3:39 PM on July 27, 2026: contributor

    <!--85328a0da195eb286784d51f73fa0af9-->

    🚧 At least one of the CI tasks failed. <sub>Task riscv32 bare metal, static libbitcoin_consensus: https://github.com/bitcoin-core/gui/actions/runs/30279603397/job/90022318535</sub> <sub>LLM reason (✨ experimental): CI failed because the Docker build’s submodule clone of newlib-cygwin.git from sourceware.org was rate-limited (HTTP 429), causing the 01_base_install.sh step to exit with code 2.</sub>

    <details><summary>Hints</summary>

    Try to run the tests locally, according to the documentation. However, a CI failure may still happen due to a number of reasons, for example:

    • Possibly due to a silent merge conflict (the changes in this pull request being incompatible with the current code in the target branch). If so, make sure to rebase on the latest commit of the target branch.

    • A sanitizer issue, which can only be found by compiling with the sanitizer and running the affected test.

    • An intermittent issue.

    Leave a comment here, if you need help tracking down a confusing failure.

    </details>

  9. polespinasa commented at 3:40 PM on July 27, 2026: member

    Key differences with #911 are:

    • Changed the font color
    • Removed the padding after "-"
    • Separated some of the changes in multiple commits
    • Changed a bit the hint box and the naming of non-mempool balance
  10. pablomartin4btc commented at 4:39 PM on July 27, 2026: contributor

    Concept ACK

    I've suggested some release notes in previous attempt #911 and it'd be nice to include them here if you're up to ofc.

    <details> <summary>Suggested Qt test snippet for <code>wallettests.cpp</code>...</summary>

    The PR touches wallettests.cpp but only to fix the existing call — worth adding a UI-level test for the new label visibility and formatting. Since there are no actual non-mempool transactions in the test wallet, calling setBalance() directly with crafted data is the right approach here rather than going through pollBalanceChanged().

    // Test non-mempool balance display
    interfaces::WalletBalances nonmempool_balances;
    nonmempool_balances.balance = walletModel.wallet().getBalances().balance;
    nonmempool_balances.nonmempool_balance = -50000;
    overviewPage.setBalance(nonmempool_balances);
    QVERIFY(overviewPage.findChild<QLabel*>("labelNonMempool")->isVisible());
    QVERIFY(overviewPage.findChild<QLabel*>("labelNonMempoolText")->isVisible());
    CompareBalance(walletModel, -50000, overviewPage.findChild<QLabel*>("labelNonMempool"));
    
    nonmempool_balances.nonmempool_balance = 0;
    overviewPage.setBalance(nonmempool_balances);
    QVERIFY(!overviewPage.findChild<QLabel*>("labelNonMempool")->isVisible());
    QVERIFY(!overviewPage.findChild<QLabel*>("labelNonMempoolText")->isVisible());
    

    </details>

  11. polespinasa commented at 5:23 PM on July 27, 2026: member

    Added the tests with you as a co-author and added some release notes. For some reason I forgot to add the release notes before.

  12. polespinasa force-pushed on Jul 27, 2026
  13. pablomartin4btc commented at 12:44 PM on July 28, 2026: contributor

    ACK 1907923c129509ee96a7d894ebc93f7517486eb0

  14. hebasto commented at 5:52 PM on July 29, 2026: member

    @GBKS

    Could you please weigh in on the UI/UX design choices in this PR?

  15. GBKS commented at 1:55 PM on July 30, 2026: none

    Yes, I'd be happy to.

    Overall, I think a label like "On hold" or "Needs attention" would be a more clear than "Not in mempool" and go better with "Available" and "Pending". Users have mental models for those.

    Not sure if this is done already, and maybe not part of this PR, but carrying this state through the rest of the UI is likely also a good idea. So a transaction in the payment history should also indicate this state. And the transaction details view can ideally let the user know why the transaction is "on hold", and provide information or options on how to either cancel it or fix the respective problem.

    Hope that's helpful.

  16. polespinasa commented at 2:27 PM on July 30, 2026: member

    Thanks for the feedback Christoph!

    Overall, I think a label like "On hold" or "Needs attention" would be a more clear than "Not in mempool" and go better with "Available" and "Pending". Users have mental models for those.

    I will go with "On hold", "needs attention" is a bit misleading as it doesn't really means that the user need to pay attention to it or do something specific other than wait.

    Not sure if this is done already, and maybe not part of this PR, but carrying this state through the rest of the UI is likely also a good idea. So a transaction in the payment history should also indicate this state. And the transaction details view can ideally let the user know why the transaction is "on hold", and provide information or options on how to either cancel it or fix the respective problem.

    I think this is a bit out of the scope of this PR, but I like the idea. I will keep this PR as is and I will try to think, as a follow-up, on how to add it to the payment history and tx details, it will mainly depend on the wallet interface giving that specific information.

    Edit: Just did some checking on this last point, the transaction does appear in the transaction history, and the tx details says that is not in the mempool, probably the phrasing could be better:

    <img width="1025" height="213" alt="imagen" src="https://github.com/user-attachments/assets/fe0bf249-bda9-4b95-b6b8-df96945fb9e9" />

    <img width="634" height="285" alt="imagen" src="https://github.com/user-attachments/assets/6a711fdd-d824-4f88-aecc-a49ec02560d4" />

    Any suggestion on how could it be more explicit in the "recent transactions", an "transaction list"? This is "transaction list" <img width="1007" height="111" alt="imagen" src="https://github.com/user-attachments/assets/d230df1d-f963-4df6-a105-1107288bd4c2" />

  17. gui: Add non-mempool balance to wallet overview called OnHold
    The assert in formatWithPrivacy is removed because m_mine_nonmempool is always negative, making this assert
    no longer true.
    
    Co-authored-by: Anthony Towns <aj@erisian.com.au>
    c674768088
  18. test: Add test for non-mempool balance visibility
    Co-authored-by: Pablo Martin <pablomartin4btc@gmail.com>
    e42c195428
  19. add release note 4894a79e29
  20. polespinasa force-pushed on Jul 30, 2026
  21. pablomartin4btc commented at 9:03 PM on July 31, 2026: contributor

    Regarding the label choice: I think "On hold" implies something or someone intentionally paused the transaction — but could be that the network doesn't even know it exists. For the policy-rejection cases, it's closer to a draft: created, saved locally, but rejected or never submitted. Nothing is on hold. "Pending" is already taken mentally by "in mempool, waiting for confirmation." And "Unbroadcast" isn't accurate either — the tx may have been broadcast and rejected by policy.

    The Core RPC in bitcoin/bitcoin#33671 uses nonmempool — so I think the GUI label should mirror that for consistency, it matches what users would see in getbalances RPC.

    The nonmempool state actually covers a wider range of situations than the PR description suggests:

    Case Duration Voluntary? Tx fate
    Private broadcast in-flight ~1 second Yes Will enter mempool
    walletbroadcast=0 Indefinite Yes User controls
    Low feerate / too many ancestors Indefinite No May enter if conditions change
    Too large OP_RETURN Indefinite No Will never enter standard mempool
    Mempool eviction Indefinite No May re-enter if feerate improves

    Perhaps this also means the tooltip needs updating. "Balance for wallet transactions that currently don't fit node's mempool policies" is not completely right, for the first two rows — a private broadcast tx fits mempool policies fine, it's just being relayed privately via Tor/I2P. Notably, the nonmempool balance was needed as a next step once private broadcast was implemented — without it, I think funds would silently disappear during the ~1 second broadcast window.

    The tooltip is also misleading on the accounting side: per Core's #33671 description, inputs consumed by non-mempool txs are added back into trusted (Available) as if the transaction doesn't exist, with nonmempool as the offsetting debit — keeping the total balance unchanged. It's not a separate pool of frozen funds.

    A more accurate tooltip I think, could be something like: "Wallet transactions not currently in the mempool — due to policy rejection, pending private broadcast, or deliberate delay."


github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin-core/gui. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-08-02 17:20 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me