Skip to content

Receive requests page #553

Open
epicleafies wants to merge 12 commits into
bitcoin-core:qt6from
epicleafies:receive-requests
Open

Receive requests page #553
epicleafies wants to merge 12 commits into
bitcoin-core:qt6from
epicleafies:receive-requests

Conversation

@epicleafies
Copy link
Copy Markdown
Contributor

@epicleafies epicleafies commented Apr 25, 2026

Redesigned the receive page and added the receive details page.
Moved QR code and receive address to the receive details page.
Added BIP21 URI as dominant receive request format.
Added receive requests to the activity log page.
Added unit, qml and functional tests for the receive functionality.
Note: the sharing functionality was decided as out of scope for this PR, the button exists but is disabled.
#518

image image image image image

@johnny9
Copy link
Copy Markdown
Collaborator

johnny9 commented Apr 26, 2026

Hold off on redesigning the Receive page. The Payment request page is good and showing the requests in the Activity list is key.

I will test/review to understand your "View previous payment requests" label and how the relationship between the Activity list and the Payment request page

Copy link
Copy Markdown
Collaborator

@johnny9 johnny9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I think we want to keep the Receive just a single page so lets drop the redesign of that from the PR. I think the link the view previous payment requests is good and should be added to the Receive page.

Then, in the Activity list, when you click on a Pending payment request, pull up the Payment request details page that you created instead of the regular transaction list. Even better is if you can join the list of received transactions and the payment requests so that you can click on a received transaction and then have a list of the payment requests that might be related.

epicleafies added 12 commits May 4, 2026 20:48
Move QmlReceiveRequestRecipient and QmlRecentRequestEntry from an
anonymous namespace in walletqmlmodel.cpp into a dedicated header so
they can be shared with the upcoming ReceiveRequestHistoryModel.

Bump the recipient serialization version to 2, adding an optional
noteSelf field, and widen the date serialization type to int64_t to
avoid Y2038 truncation.
Introduce a QAbstractListModel that manages the in-memory list of
receive request entries. It exposes roles for address, label, amount,
BIP21 URI, and timestamps, and provides static helpers for
serialization, deserialization, and bitcoin: URI construction.

Unit tests cover URI building (plain address, with params, URL
encoding, bech32 case preservation), serialization round-trips
including the v2 noteSelf field, model role queries, prepend/remove
operations, and malformed-blob resilience.
Add several properties to PaymentRequest that the upcoming detail
page needs: addressType (derived from the destination variant),
noteSelf (private note), qrPayload (reactive BIP21 URI that updates
when amount, address, label, or message change), createdIso
(ISO 8601 creation timestamp), and hasPaymentInfo (true when any of
label, message, or amount is set).
Add an isPendingRequest bool to Transaction so the activity list can
distinguish unfulfilled receive requests from real on-chain
transactions. When set, dateTimeString() returns "Pending receive"
instead of computing a relative timestamp.
Wire ReceiveRequestHistoryModel into WalletQmlModel as a persistent
child model. Refactor commitPaymentRequest() to return bool, always
generate a fresh address, and update both the history model and the
activity list on success. Add loadPaymentRequest(),
removeReceiveRequest(), and reloadReceiveRequests() for the detail
page and options menu.

In ActivityListModel, add pending-request support:
addPendingReceiveRequests() merges unfulfilled requests into the
activity feed during refresh, removePendingRequestForAddress() clears
them when a real transaction arrives, and updateTransaction() now
uses proper beginInsertRows/endInsertRows instead of a blanket
dataChanged signal.
Redesign the RequestPayment page from a flat form into a PageStack
with two views: a creation form and a detail page that shows after a
request is committed.

The detail page (PaymentRequestDetail) displays a QR code encoding
the BIP21 URI, copy and share buttons, and an expandable details
section with address, amount, label, message, address type, URI, and
creation time. A CopiedToast component provides transient clipboard
feedback.

Supporting changes:
- Add EllipsisMenuButtonItem control (non-toggle menu action)
- Add ReceiveOptionsPopup and PaymentDetailOptionsPopup components
- Extend OutlineButton with optional icon and disabled state
- Simplify IconButton and EllipsisMenuToggleItem hover handling
- Adjust Separator default color for better contrast
- Register ReceiveRequestHistoryModel QML type in bitcoin.cpp
- Handle textEdited() signal without arguments in testbridge
Add an end-to-end functional test (qml_test_receive.py) that imports
a wallet, creates two receive requests, verifies the BIP21 QR
payload includes correct amount/label/message params, confirms
history persists across a GUI restart, and checks the history count
grows correctly.

Add a QML unit test (tst_requestpayment.qml) covering the
formatRelativeTime helper and the BTC/SAT amount input validators.

Wire the functional test into the CI workflow.
The iconColor and amountColor bindings incorrectly reference
`delegate` which is not in scope — the component's root id is
`root`. This caused the color logic to silently fail at runtime.
When a real transaction arrives for an address with a pending receive
request, update the existing entry in-place rather than removing it
and inserting a new one. This preserves the entry's position in the
activity list and provides a visible transition from pending to
fulfilled.

Expose isPendingRequest to QML via a new model role so the delegate
can show a purple icon for pending entries, distinguishing them from
unconfirmed transactions which use blue.
Redesign the receive payment form with a lock-on-generate pattern:
after committing a request the form displays the inline QR and address,
and the generate button becomes "New request" to start fresh. Add edit,
cancel, and copy controls for the committed state.

Redesign the detail page options menu with add name/message/note-to-self
actions, use-as-template, and delete. Add a modal QR popup with download
and copy. Extract DetailEditRow as a reusable component.

Add isEditing and edit() to PaymentRequest so the form tracks whether
the user is creating/editing vs viewing a committed request.

Fix EllipsisMenuToggleItem binding loop and add accessibility roles
to menu items and CopiedToast. Add formatRelativeTime to shared utils.

refs bitcoin-core#518
Add usePaymentRequestAsTemplate to WalletQmlModel: creates a new
request pre-filled with an existing request's amount, label, message,
and note-to-self but with a fresh address generated on commit.

Improve commitPaymentRequest to sync the detail page when updating
the currently-viewed request. Add requestOpenReceive to
WalletQmlController for detail-to-receive-tab navigation.

Fix activity list pending request label to use tr() for translation.
Wrap time-ago strings in transaction.cpp with tr() and use singular/
plural forms. Add requestId to Transaction for pending request tracking.

refs bitcoin-core#518
Fix the test automation bridge to fall back to textEdited() when
textEdited(QString) is not found, matching Qt's actual signal
signature for TextField and LabeledTextInput.

Fix the functional test error handler to stop the GUI process before
reading its output, preventing a hang on process.stdout.read().
Add v1 deserialization and formatAmountBtc edge case tests.
Replace local formatRelativeTime with shared Utils import.

refs bitcoin-core#518
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants