Skip to content

feat: refine usdt payment and earn screens - #1494

Merged
jvsena42 merged 12 commits into
masterfrom
feat/usdt-design-followup-20261015
Oct 15, 2026
Merged

jvsena42 merged 12 commits into
masterfrom
feat/usdt-design-followup-20261015

Conversation

@ben-kaufman

@ben-kaufman ben-kaufman commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1495

This PR refines the USDT payment and Earn screens. Follow-up to merged #1432.

Description

  • Simplify Earn setup and authorization copy to the approved Figma wording while preserving required and optional address-sharing consent.
  • Keep bridge amounts in expanded technical details, with the designed icons, typography and spacing.
  • Align Home balances, receive fees, payment amount screens and completion controls with the USDT typography and spacing. Keep enable actions readable at large system text sizes.
  • Distinguish optional USDT address sharing from required sharing without changing consent or disabled-USDT behavior.
  • Localize the USD request keypad and amount while preserving exact values.
  • Keep manual entry and paste available if the scanner cannot initialize the camera, and start the camera only after permission is granted.
  • Show the confirmation checkmark before payment success, keep refund inputs readable at large text sizes, and return expanded details to the top when toggled.
  • Add deposit-history access through a floating button in Receive → network selection, with list content scrolling behind it, and place the smaller support actions side by side.
  • Float Choose Recipient over the subscription form while keeping the last fields and keyboard editing accessible.
  • Let requests and subscriptions select Savings, Spending and USDT individually. Subscriptions continue to accept Bitcoin methods or USDT; the selected methods are enforced in the proposal. Removed methods keep their asset color at 50% opacity and show + to add them back.

Out of Scope

None.

Design

Home · USDT introduction · Receive fees · Earn · USDT-only Earn · Basic confirmation · Technical details · Payment requests · Subscriptions · Deposit history entry · Funding-source menu · Small action buttons

Subscription methods follow the agreed #1000 discussion: Savings and Spending remain individually selectable, and Bitcoin methods remain mutually exclusive with USDT. Native Android text fields retain their 56 dp minimum (the Figma examples use 52 dp) and expand for larger system text.

Preview

Native captures were checked against these frames and shared in the local review gallery. They use isolated test data and verify presentation and interactions; they do not represent live payments or bridge settlement.

QA Notes

Journeys

  • updated share-receiving-details.xml — short Earn copy, optional USDT sharing and disabled behavior.
  • updated paykit-quoted-usdt.xml — individual receiving methods and selected request options.
  • updated create-and-propose.xml — subscriptions accept selected Bitcoin methods or USDT; the floating recipient action preserves scrolling, large text and keyboard access.
  • updated usdt-payment-links-and-scans.xml — plain addresses open USDT with a visible network choice, matching the paired iOS journey.
  • updated usdt-opt-in.xml — readable enable actions at large text sizes.
  • updated usdt-send-review-and-details.xml — basic confirmation and expanded technical details.
  • updated usdt-bridge-details.xml — bridge details and a floating deposit-history action, including scrolling and large text.
  • updated usdt-bridge-support.xml — compact support actions and refund history.

Manual Tests

  • docs/usdt-qa.md → Android camera availability: camera failure leaves manual entry and paste usable. A no-camera emulator is required for this hardware fault.

Automated Checks

  • added PaymentRequestAmountLocaleTest.kt — German comma input preserves trailing decimals and submits the exact cents.
  • added PaykitAcceptedMethodsTest.kt — German method labels remain reachable at 280 dp with 1.5× text scaling.
  • updated PaykitRequestPricingTest.kt — filters subscription methods by selection, asset and current availability.
  • updated PaykitPaymentRequestRepoSubscriptionTest.kt — sends only the selected subscription endpoint.
  • updated CreatePaymentRequestScreenTest.kt — individual request-method selection and removal.
  • updated CreateSubscriptionScreenTest.kt — selected method controls and unavailable submissions.
  • updated UsdtPaymentContentTest.kt — expanded bridge details, full-address layout, immediate confirmation, pending-to-success transitions, and return from payment details.
  • updated UsdtBridgeDetailsTest.kt — refund input remains usable at large text sizes.
  • ran targeted instrumentation — 23 retained UI tests passed on the merged source, including localized amount entry, requests, amount screens, confirmation and bridge details; all five confirmation tests passed again after the final divider fix.
  • ran isolated native checks — Earn enabled/disabled states, actual subscription-sheet method and amount changes, bridge confirmation, full-address expansion, deposit-history access, funding-menu dimensions and compact support actions. The real-sheet check used a disposable fixture; it is not a retained full-sheet regression test.

Local validation: 4,222 unit tests and 19 focused native UI tests passed after rebasing on master, including the new translations. After the submission-transition fix, the full unit suite and all seven payment UI tests passed again. The final build passed. The complete detekt report was inspected against the prior report and current master; no introduced violations remain. Subscription footer checks passed at normal and enlarged text sizes, including Name and Description editing above the keyboard. Native captures cover normal and large text, Home balances, send/receive, fees, completion and Earn. These checks do not exercise live payments or bridge settlement.

Camera failure validation: reproduced the crash on the preceding build with both emulator cameras disabled. The fix preserves manual entry and valid-address paste through to the amount screen, including after reopening the scanner. Permission denial is safe, and granting permission on a camera-enabled emulator starts the live preview. No payment was submitted. Compile, all 4,222 unit tests, APK build and detekt passed; the complete detekt report remains at the same 1,401 existing findings with none introduced.

@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect bounded payment and USDT wallet workflows.

The PR appears safe to merge, with non-blocking improvements needed for larger-text layouts and subscription interaction tests.

Findings

  1. P2 Payment labels can get clipped ▶
  2. P2 Method clicks remain untested ▶

Summary

Refines Earn consent and USDT payment details, adds a clearer deposit-history action, and separates Savings, Spending, and USDT selection.

  • Payment requests and subscriptions offer Savings, Spending, and USDT separately.
  • USDT confirmations show bridge amounts and networks after you open Details.
  • Earn consent, deposit history, and bridge support actions get simpler screens.

Intentional presentation changes: ben-kaufman explicitly requested bridge amounts only in expanded details, shorter Earn disclosures, and Bitcoin-or-USDT subscription selection. These were not treated as defects.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Choose payment methods] --> B[Filter by subscription asset]
  B --> C[Create subscription draft]
  C --> D[Intersect with current receiving methods]
  D --> E{Any methods remain?}
  E -->|Yes| F[Send proposal with selected methods]
  E -->|No| G[Reject creation]
Loading

Reviews (1) · Last reviewed commit: "feat: refine usdt payment and earn scree..." · Reviewed by Greptile

Comment thread app/src/main/java/to/bitkit/ui/components/PaykitAcceptedMethods.kt Outdated

@talosmachina talosmachina 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.

No findings. Splits accepted methods into Savings, Spending and USDT chips for requests and subscriptions, threads the subscription selection into the proposal endpoints, and moves the bridge amounts into expanded details. Reviewed 8bcefb0, full tier.

What I checked, and 6 candidates I ruled out

Read in full: PaykitRequestPricing.kt (subscriptionEndpoints), PaykitPaymentRequestRepo.kt (proposeSubscription, subscriptionProposalEndpoints, acceptedPaymentEndpointIdentifiers), PaykitAcceptedMethods.kt, CreateSubscriptionScreen.kt, CreatePaymentRequestScreen.kt (PaymentRequestDetailsContent), PubkyAuthApprovalSheet.kt and its view model's USDT state, UsdtSendContent.kt, UsdtDepositReceiveScreen.kt, strings.xml hunks
Call sites traced: subscriptionEndpoints (sheet and repo), PaykitPaymentOption.endpoints, every reference to the four removed string keys (none left)
CI: lint, detekt, build-local green. build red on one unit test, PubkyAuthManifestTest > "signup and authorization links resolve only through their enabled aliases"; the same test failed on run 38600594609 of the stacked base branch at c51f3bd, an ancestor of this head, and this diff touches neither the manifest nor that test. e2e-tests-local still running at review time.
Not built here: Android builds of a PR branch are not run on this reviewer; CI is the gate.

Ruled out

  • Proposal sends a method the user deselected: the repo intersects the draft selection with the live accepted list (selected != null && it !in selected), and the new repo test asserts the proposal carries exactly [P2wpkh].
  • Empty selection still submits: acceptedMethods.isNotEmpty() gates Choose Recipient, and an empty intersection throws RequestUnavailable in the repo.
  • Stale selection after an asset change on the amount screen: onContinue clears restrictedMethods when the asset changes, and the chip path replaces it with the new asset's endpoints.
  • Required USDT claim cannot be approved once the switch is hidden: loadUsdtAddress sets shareUsdt to true when usdtRequired and an address loaded, so canAuthorize holds.
  • Payment request selection outliving availability: selectedMethods now filters by availableMethods, so a method that disappears is dropped from the draft.
  • Bridge cost and estimate no longer on the basic confirmation: matches the stated design (amounts kept in expanded details), so plausibly deliberate.

Merge confidence: 3/5, CI build is red on PubkyAuthManifestTest, which also fails on the base branch and is not tied to this change.

ovi-reviewer[bot]

This comment was marked as resolved.

@ovi-reviewer

This comment has been minimized.

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Regtest APK

Built from ff127b0 (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@ben-kaufman

Copy link
Copy Markdown
Contributor Author

Current head 93da6f0 now passes CI build, all unit tests (including PubkyAuthManifestTest), lint and the E2E build: https://github.com/synonymdev/bitkit-android/actions/runs/38730878107. The earlier manifest-test failure also occurs in ancestor c51f3bd (run 38600594609), with the relevant source and configuration unchanged, so no workaround was added. E2E scenario jobs are still running. The layout and screen-map fixes are posted, and the subscription-test coverage and its limits are explained in the review thread.

ovi-reviewer[bot]

This comment was marked as outdated.

@ovi-reviewer

This comment has been minimized.

ovi-reviewer[bot]

This comment was marked as outdated.

@piotr-iohk piotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

QA review

Scope: Follow-up review of changes since 93da6f0, including affected callers and prior comments, at 2057b38. Inherited baseline bc-59fb3e88-b55a-461b-b1eb-66a8d94f39eb still covers payment-request and subscription method selection, USDT confirmation details and the quoted swipe amount, deposit history, bridge support, Earn authorization, the funding-source menu, and the earlier journey and test updates.

No new actionable code findings.

This pass covers text-style parameters on buttons, sheet titles, swipe confirmation, and the USDT available balance, plus the new bare-address steps in journeys/usdt-payment-links-and-scans.xml. Those steps match the existing scan, paste, manual-continue, hardware-warning, and enable-resume router. Earlier chip-wrapping and screen-map comments are addressed in the inherited revision: method chips use FlowRow, and the cited node id is gone from the screen map.

CI build passed on this head. This review did not rerun tests or start a device.

Ready for device testing.

Device testing: not performed in this review.

@ovi-reviewer

This comment has been minimized.

@ovi-reviewer

This comment has been minimized.

@jvsena42 jvsena42 left a comment •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

No HIGH or MEDIUM. Three LOW findings, inline. Reviewed 2057b38. I reviewed this as a funds and consent change: the send confirmation, payment-request and subscription endpoints, and the Earn approval.

Checked and clean:

  • Send confirmation. Payment is quote.amount, Fee is maximumFee, Max total debit is amount + maximumFee, and Recipient gets is receivedAmount, with ± only for Orchestra (UsdtSendContent.kt:664-692). Swipe gating is unchanged. Moving the bridge amounts into expanded details is the agreed design and is not raised.
  • Subscriptions. acceptedMethods is recomputed against the live receiving methods on every composition. A cross-asset tap replaces the restriction, and Amount Continue clears it on an asset change. The repo intersects the draft with the live list and the asset, and an empty result throws RequestUnavailable (PaykitPaymentRequestRepo.kt:896-903). Sheet state is dropped on cancel. Back keeps the selection, as intended.
  • Payment requests. selectedMethods filters by availability, and Send is disabled on an empty selection. The repo re-intersects with the live list.
  • Earn consent. The ViewModel is unchanged. A required claim still needs shareUsdt && usdtAddress != null, and validatedUsdtEndpoint rejects an endpoint that differs from the one shown.
  • Bare 0x input. Android already routes Enter Manually, the scanner and paste through isUsdtPaymentInput (AppViewModel.kt:6745). The iOS twin's Enter Manually does not, which I raised on synonymdev/bitkit-ios#942.
  • Figma, all 9 linked frames:
    • Earn, USDT-only Earn, basic confirmation, technical details, payment requests, subscriptions, deposit-history entry, funding-source menu and small action buttons were checked for spacing, type, tokens, states and icons. That includes ic_arrow_*_right and ic_plus_small against the exported frame assets, and the removed-chip 50% opacity with +.
    • No deltas apart from the two inline LOWs (the expanded-address divider and the screens-map name).
    • The middle-ellipsis address matches the Bitcoin review screen and is kept deliberately.
  • Performance. Not performance-relevant: a FlowRow of at most three chips and style changes, with no new polling, waits or locks.

The LOWs do not block approval, which follows the device gate. Each can be fixed here or moved to a follow-up issue, your choice. Please reply on each thread saying which.

Device gate (partial): 2057b38 — not run yet; J1–J7 pending (USDT fixture for J1/J4–J7, two linked wallets for J2/J3). The device result will follow in a second review.

Comment thread app/src/main/res/values/strings.xml
Comment thread app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtSendContent.kt Outdated
Comment thread docs/screens-map.md Outdated
@ben-kaufman

ben-kaufman commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

Updated with the latest master, including Piotr’s UI-test changes, and resolved the conflicts.

Fixed the German USD entry issue: the amount and keypad now use the locale separator while retaining the exact canonical value. A native test enters 150,50 and confirms 15,050 cents.

For the camera report, the zero-camera detail made it reproducible. Fixed in 76e1803c0: camera initialization now waits for permission and handles initialization/binding failures without closing Send. Verified on an API 36 emulator with both cameras disabled: denied permission, manual entry, valid-address paste through to the amount screen, and reopening the scanner all work without a crash. On the same emulator with cameras enabled, granting permission starts the live preview. No payment was submitted. The missing test balance and archived bridge fixture remain setup requirements for the funded journeys.

Validation: 4,222 unit tests and 23 focused native UI tests passed; the confirmation tests were rerun after the final divider fix. Compile passed, and the complete lint report has no introduced findings. Also applied the broader Figma typography, spacing and accessibility corrections, and requested another review.

The camera fix also passed compile, all 4,222 unit tests, APK build and the full detekt comparison (no introduced findings). Added its hardware-failure checks to docs/usdt-qa.md.

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more design delta from the Figma pass.

Comment thread app/src/main/java/to/bitkit/ui/screens/wallets/usdt/UsdtDepositReceiveScreen.kt Outdated
@ben-kaufman
ben-kaufman requested a review from jvsena42 October 15, 2026 17:55

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

One more Figma delta on Create Subscription.

Comment thread app/src/main/java/to/bitkit/ui/screens/subscriptions/CreateSubscriptionScreen.kt Outdated
@ben-kaufman
ben-kaufman requested a review from jvsena42 October 15, 2026 18:23

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Device results for 2057b38 (Pixel 9 plus a second emulator as payer, local USDT fixture on an Arbitrum fork).

No new findings. Both open questions were checked against an origin/master build on the same fixture:

  • Correction to my partial comment: the Copy toolbar on the bridge address long-press works. Copy / Select all appears on both the PR and master, and Select all → Copy puts the full address on the clipboard. My earlier miss was screenshot timing.
  • Celebration not shown after deposit details: if a USDT transfer arrives while deposit details are open, the received celebration never appears after returning to the wallet. Master does the same, so it is out of scope for this PR.

Journeys:

  • J1 Earn / receiving details: 1–6 and 8–17 pass. Step 7 could not be forced (the address is derived locally); 18–19 need a funded-wallet restore and were not run.
  • J2 quoted USDT requests: 1, 2 and 4–15 pass. The comma-locale steps (3, parts of 8/9/13) and 16 were not run.
  • J3 create and propose: all 22 pass. Step 17 is confirmed from the log (SubscriptionTooLong).
  • J4 links and scans: 1–12, 14, 16 and 17 pass; a bare 0x via scanner, Paste and Enter Manually all open USDT send. Hardware-wallet sub-steps were not run. Step 15 shows "Not enough USDT to cover the amount and fees." rather than the journey's wording (unchanged step).
  • J5 send review / details: all 12 pass.
  • J6 bridge details: 3–7 and 9–14 pass; 1–2 not reproduced (a 1-confirmation transfer never showed as pending); 8 is the master issue above.
  • J7 bridge support: all pass. Step 9 says "Refund in progress" where the journey says "Refunding".

Figma: 9 frames compared.

  • Technical details, address expanded: the gap from Hide Details to the fee note is about 4dp against about 21dp in the frame. At 360dp width, Hide Details falls below the fold, but it can be reached by scrolling. Both are LOW; 1c37a7e may cover the first.
  • Subscriptions: separate SAVINGS / SPENDING chips against one BITCOIN chip in the frame, as the PR body intends.
  • The other six frames match.

l10n: de, pt-BR, el, fr, ru, es and ar at 360dp, no clipping or overflow; Arabic mirrors correctly. The changed USDT/auth keys have no translations yet.

Commits since 2057b38 (86e370c…f43cb25) still need a delta review before approval.

Device gate: 2057b38 — journeys: 7 run, 0 failed (sub-steps not run in J1, J2, J4, J6, J7; journey-wording mismatches in J4 a15, J7 a9); perf: not relevant, no ANR or crash; Figma: 9 screens compared, 3 deltas (LOW); l10n: 3 changed keys plus chip/detail labels checked in de, pt-BR, el, fr, ru, es, ar at 360dp, 0 overflow

jvsena42
jvsena42 previously approved these changes Oct 15, 2026

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Approving at f43cb25.

The device gate passed at 2057b38 (results in my previous review). The commits after it (86e370c, 1c37a7e, 9c75d43, 76e1803, c46da49, f43cb25) got a code-level delta review:

  • Submitted-payment transitions (9c75d43): no double submit (confirm()/send() guards, swipe disabled while busy or completed). Back hides for the whole submitted window. Both hosts dismiss rather than pop once submitted, so a confirmed payment cannot reopen the review.
  • Auth approval sheet: copy only. canAuthorize and the required-claim gating are unchanged.
  • Scanner (76e1803): bind waits for permission and a bind failure toasts instead of crashing. The scan result still goes through the same onScanSuccess routing.
  • Floating buttons (c46da49, f43cb25): bottom padding equals the measured footer height, enabled state and test tags are kept, and the IME case on Create Subscription shrinks the viewport.
  • All five earlier LOWs are fixed at head.

CI is green at head. One LOW inline: a journey still describes the old deposit button layout.

Device gate: 2057b38 — journeys: 7 run, 0 failed (sub-steps not run in J1, J2, J4, J6, J7; journey-wording mismatches in J4 a15, J7 a9); perf: not relevant, no ANR or crash; Figma: 9 screens compared, 3 deltas (LOW); l10n: 3 changed keys plus chip/detail labels checked in de, pt-BR, el, fr, ru, es, ar at 360dp, 0 overflow. Commits after 2057b38 reviewed in code, not re-run on device.

Comment thread journeys/usdt-bridge-support.xml Outdated
@jvsena42

Copy link
Copy Markdown
Member

Out of scope for this PR: either already on master or not changed here. Listing them so they aren't lost. None of these block the approval.

  • Received celebration dropped: if a USDT transfer arrives while deposit details are open, the celebration never appears after returning to the wallet. Reproduced the same way on master.
  • Raw provider codes shown to users: standing_route_unavailable under the refund field, and BRIDGE_NEEDS_ATTENTION in the Copy Details text.
  • USDT-only request reopen: shows a "preparing" summary for about 10 s with an orange Swipe To Pay and orange From/For icons.
  • Funding-source menu: sits about 2.7dp from the screen edge when the source pill is short.
  • Auth approval: Android has no relay-origin disclosure, and shareUsdt defaults to ON.
  • Review screen: no longer shows the bridge provider name.
  • Journey wording: J4 step 15 and J7 step 9 differ from the app ("Not enough USDT to cover the amount and fees.", "Refund in progress").

@ben-kaufman

Copy link
Copy Markdown
Contributor Author

Thanks John. Fixed the two stale journey expectations in 05453b2 and mirrored them on iOS: entering the full balance now expects "Not enough USDT to cover the amount and fees.", and the pending refund expects "Refund in progress". Also made the balance step explicitly use another owned wallet's address after the self-send check.

These are documentation-only corrections. XML and cross-platform action parity checks pass, and detekt has no introduced findings. Your Copy correction and the existing master celebration behavior need no changes here. Re-requested review for the commits since your device-tested 2057b38.

jvsena42
jvsena42 previously approved these changes Oct 15, 2026

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-approving at 05453b2. The only change since my approval is 05453b2, which rewords two journey steps to match the app ("Refund in progress", "Not enough USDT to cover the amount and fees."). The LOW at usdt-bridge-support.xml:9 (deposit button layout) is still open.

ovitrif
ovitrif previously approved these changes Oct 15, 2026

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Approving at 05453b2, code review only (no device runs), after @jvsena42's approval.

Since our review at 1c37a7e: the confirmed-send flash from our LOW is fixed (9c75d43: Submitted stays until success, Back is off once submitted); the scanner now reports a camera that fails to start instead of crashing (76e1803); the subscription and deposit-history changes (c46da49, f43cb25) move layout only, with the same Continue conditions. Nothing new at MEDIUM or above.

The Earn consent wording from our earlier review stays a product call.

@ben-kaufman
ben-kaufman dismissed stale reviews from ovitrif and jvsena42 via ff127b0 October 15, 2026 20:18

@jvsena42 jvsena42 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Re-approving at ff127b0. The only change since my approval is ff127b0, which updates the deposit-button journey step and the QA doc to the pinned layout. That fixes my LOW on usdt-bridge-support.xml:9.

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

utAck

@jvsena42
jvsena42 merged commit 0801188 into master Oct 15, 2026
21 checks passed
@jvsena42
jvsena42 deleted the feat/usdt-design-followup-20261015 branch October 15, 2026 21:28
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.

feat: usdt payment and earn screens match the final designs

5 participants