Skip to content

feat(ui): use the shared amount entry for contact payments - #930

Merged
romchornyi merged 2 commits into
developfrom
feat/contact-pay-shared-amount-entry
Aug 7, 2026
Merged

feat(ui): use the shared amount entry for contact payments#930
romchornyi merged 2 commits into
developfrom
feat/contact-pay-shared-amount-entry

Conversation

@romchornyi

@romchornyi romchornyi commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Issue being fixed or feature implemented

The contact Pay sheet took its amount through a bare TextField + .decimalPad, while every other send surface in the app uses DashUIKit.EnterAmountView. The system keyboard let through input the parser then had to rescue — a locale comma, a bare separator, more precision than DASH carries — so what was typed and what was sent could disagree. There was also no fiat line, no Max, and none of the shared validation.

The confirmation compounded it: it echoed amountText back rather than reporting what was broadcast, so any gap between the two rendered as a truthful-looking "sent" line for an amount that never left the wallet.

What was done?

  • EnterAmountView + NumericKeyboardView replace the raw TextField and the system keypad, matching SendAmountScreen and InternalTransferScreen. That brings the fiat line, a Max button, and the shared parsing/validation the rest of the app already relies on.
  • The confirmation now states the broadcast amount. A new sentAmountDuffs is captured at send time and rendered instead of the typed text.
  • Sheet detent goes .medium.large, since the sheet now carries its own keypad and needs the room the system keyboard used to occupy.

One file, +44/−33.

Note the Max button leans on maxSendable, which #928 corrected to the wallet-wide spendable balance — so Max here is accurate on top of current develop in a way it would not have been before that landed.

How Has This Been Tested?

Testnet, on device. Paid an established DashPay contact from the profile sheet: the keypad rejects a second separator and over-precision instead of silently reshaping the value, the fiat line tracks the entry, Max fills the spendable balance, and the confirmation reports the amount that was actually broadcast.

This commit was written alongside #918 and tested in the same sessions; it is split out here because it is a Pay-sheet UI change rather than part of the payment-history restore, and it did not make it into that PR before it merged.

Breaking Changes

None. UI-only, single screen.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

Summary by CodeRabbit

  • New Features

    • Added a redesigned payment amount entry experience with a numeric keypad.
    • Added fiat currency conversion and support for entering the maximum available amount.
    • Improved payment confirmation by displaying the exact amount broadcast.
  • Bug Fixes

    • Added validation for parsed payment amounts.
    • Expanded the payment sheet for easier amount entry and review.

The Pay sheet took its amount through a bare `TextField` + `.decimalPad`
while every other send surface uses `DashUIKit.EnterAmountView`. The
system keyboard let through input the parser then had to rescue — a
locale comma, a bare separator, precision DASH does not carry — so what
was typed and what was sent could disagree, and there was no fiat line,
no Max, and no shared validation.

Adopt the standard component over the app's own keypad, as
`SendAmountScreen` and `InternalTransferScreen` do.

The confirmation now states the amount that was broadcast rather than
echoing the typed text back: any gap between the two rendered as a
truthful-looking "sent" line for an amount that never left the wallet.
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@romchornyi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 502539b0-7423-4061-bbaa-7e705eb3a2ff

📥 Commits

Reviewing files that changed from the base of the PR and between 5c3f699 and 296556d.

📒 Files selected for processing (1)
  • DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift
📝 Walkthrough

Walkthrough

The contact payment sheet now uses shared amount-entry controls with fiat conversion, max-send support, and parsed-amount validation. It records the exact duff amount broadcast and shows that amount in payment confirmation.

Changes

Contact payment amount

Layer / File(s) Summary
Shared amount entry and validation
DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift
The sheet uses a large detent and replaces the raw decimal field with EnterAmountView and NumericKeyboardView. The Pay action requires a valid parsed amount and no active send.
Broadcast amount confirmation
DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift
The sheet stores the parsed duff amount after a successful payment. Confirmation displays the stored amount or falls back to the typed text.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ContactProfileSheet
  participant EnterAmountView
  participant NumericKeyboardView
  participant PaymentConfirmation
  NumericKeyboardView->>EnterAmountView: enters amount
  EnterAmountView->>ContactProfileSheet: returns parsed amount
  ContactProfileSheet->>PaymentConfirmation: provides exact broadcast amount
Loading

Suggested reviewers: quantumexplorer

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: using shared amount-entry components for contact payments.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/contact-pay-shared-amount-entry

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift`:
- Line 541: Remove the redundant nil initializer from the sentAmountDuffs `@State`
declaration in ContactProfileSheet, leaving it as an implicitly initialized
optional while preserving its UInt64? type and state behavior.
- Around line 582-583: Move the `@ViewBuilder` attribute onto the same line as the
form property declaration in the form computed property, preserving its existing
behavior and body.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a71e62a-8bb6-440e-80ac-ac3c25f8ef0a

📥 Commits

Reviewing files that changed from the base of the PR and between e771a11 and 5c3f699.

📒 Files selected for processing (1)
  • DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift

Comment thread DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift Outdated
Comment on lines 582 to 583
@ViewBuilder
private var form: some View {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Put @ViewBuilder on the property declaration line.

SwiftLint requires attributes on the same line as variable declarations.

Proposed fix
-    `@ViewBuilder`
-    private var form: some View {
+    `@ViewBuilder` private var form: some View {

As per coding guidelines, Swift files must follow SwiftFormat/SwiftLint.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@ViewBuilder
private var form: some View {
`@ViewBuilder` private var form: some View {
🧰 Tools
🪛 SwiftLint (0.65.0)

[Warning] 583-583: Attributes should be on their own lines in functions and types, but on the same line as variables and imports

(attributes)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@DashWallet/Sources/UI/DashPay/Contacts/SwiftUI/ContactProfileSheet.swift`
around lines 582 - 583, Move the `@ViewBuilder` attribute onto the same line as
the form property declaration in the form computed property, preserving its
existing behavior and body.

Sources: Coding guidelines, Linters/SAST tools

`redundant_optional_initialization` is a SwiftLint default and this
config does not disable it, so a newly added `= nil` is a new violation
even though its neighbours predate the rule.
@romchornyi
romchornyi merged commit 852f8f3 into develop Aug 7, 2026
2 checks passed
@romchornyi
romchornyi deleted the feat/contact-pay-shared-amount-entry branch August 7, 2026 18:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants