Skip to content

feat: refine usdt payment and earn screens - #942

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

jvsena42 merged 10 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 #943

This PR refines the USDT payment and Earn screens after #884.

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.
  • Keep method chips readable with long translated names, and let users expand the full recipient address before paying with aligned address/network dividers.
  • Accept plain USDT addresses from the general scanner and manual entry, while preserving opt-in and hardware-wallet restrictions.
  • Keep the receive loading/error screen compatible with the current QR component and its edit navigation.
  • 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.

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 — raw addresses and payment links route consistently, with opt-in and clipboard safeguards.
  • 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

N/A

Automated Checks

  • updated UsdtWalletUITests.swift — ordinary manual entry routes a bare address to USDT, preserves it on back navigation, and offers the network chooser.
  • updated PaykitRequestPricingTests.swift — filters subscription methods by selection, asset and current availability.
  • updated PaykitPaymentRequestServiceTests.swift — sends only the selected subscription endpoint.
  • updated UsdtPaymentLinkTests.swift — accepts raw addresses, rejects malformed recipients, preserves hardware scope and suppresses disabled automatic clipboard prompts.
  • ran isolated native checks — Earn and authorization enabled/disabled states, removable request methods, mutually exclusive subscription assets, exact amount restoration, German labels at 320 pt, full-address expansion, bridge details, deposit-history access, compact support actions and funding-menu dimensions/opacity.

Local validation: 86 focused display, support, payment-link, pricing, authorization, receive-refresh and manual-entry tests passed after rebasing on master. The final native render build passed. All 35 changed Swift files pass SwiftFormat; translation validation has no errors, with the previously accepted English fallback for new copy. 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, Earn and expanded address dividers. These checks do not exercise live payments or bridge settlement.

@greptile-apps

greptile-apps Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes reach several wallet workflows, but stay within Paykit, USDT, and Earn screens.

The PR appears safe to merge, with non-blocking improvements for translated payment choices and full-address review.

Findings

  1. P2 Payment choices get squeezed ▶
  2. P2 Full recipient address stays hidden ▶

Summary

This PR updates Earn and USDT payment screens and adds separate receiving-method choices.

  • Requests and subscriptions can choose Savings, Spending, and USDT separately.
  • USDT send details and bridge actions are easier to find.
  • Earn introductions use shorter copy and keep sharing choices up front.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    A["Choose receiving methods"] --> B["Store selected methods in draft"]
    B --> C["Filter by asset and availability"]
    C --> D{"Any methods left?"}
    D -- No --> E["Block proposal"]
    D -- Yes --> F["Recheck before sending"]
    F --> G["Send proposal with selected methods"]
Loading

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

Comment thread Bitkit/Components/PaykitAcceptedMethods.swift Outdated
Comment thread Bitkit/Views/Wallets/UsdtSendView.swift Outdated
ovi-reviewer[bot]

This comment was marked as 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. iOS side of the same change: per-method Savings, Spending and USDT chips for requests and subscriptions, the subscription selection carried into the proposal and its pre-send recheck, bridge amounts moved into expanded details, and the relay line dropped from the Earn intro (it stays in the authorization screen). Reviewed b817d74, full tier.

What I checked, and 5 candidates I ruled out

Read in full: PaykitRequestPricing.swift (subscriptionEndpoints), PaykitPaymentRequestService.swift (proposeSubscription and the endpoint recheck before sending), PaykitAcceptedMethods.swift, CreateSubscriptionView.swift, SubscriptionsView.swift (SubscriptionSheet), CreatePaymentRequestView.swift, PubkyAuthApprovalSheet.swift, UsdtSendView.swift, Localizable.strings hunks
Call sites traced: subscriptionEndpoints (view, propose, recheck), PaykitSubscriptionDraft construction (the new optional field defaults to nil in the memberwise init), relayOrigin (still rendered by relayOriginSection in the authorization screen), every reference to the removed string keys (none left)
CI: Run Tests still running at review time; Greptile passed.
Not built here: iOS does not build on this reviewer's Linux host, so this is reasoned from the code; Run Tests is the gate.

Ruled out

  • Recheck before sending disagrees with the first computation: both calls pass the same draft.acceptedPaymentEndpointIdentifiers, so the guard only trips when availability really changed.
  • Empty selection still submits: the details button is disabled on acceptedEndpoints.isEmpty, and the service's guard rejects an empty list.
  • Stale selection after an asset change on the amount screen: onContinue resets the selection to nil when the asset changes.
  • Required USDT claim cannot be approved once the switch is hidden: loadUsdtAddress sets shareUsdt = true for a required claim once the address loads.
  • Relay disclosure lost: removed from the intro only; the authorization screen still shows it.

Merge confidence: 4/5, no findings, but Run Tests had not finished and the Swift is not built here.

Base automatically changed from feat/usdt-pr-ready-20261006 to master October 15, 2026 11:54
@ben-kaufman
ben-kaufman force-pushed the feat/usdt-design-followup-20261015 branch from e0f1cae to 390fb9c Compare October 15, 2026 12:01
@ovi-reviewer

This comment has been minimized.

ovi-reviewer[bot]

This comment was marked as outdated.

ovi-reviewer[bot]

This comment was marked as outdated.

@ovi-reviewer

This comment has been minimized.

@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: Reviewed the full PR diff against its merge base, at 87315a3.

1 actionable finding — resolve or provide an evidence-backed rebuttal.

Payment-request and subscription method selection, proposal endpoint filtering, USDT review amounts, deposit history, bridge support, Earn authorization, and the funding-source menu match the updated journeys. Bare 0x addresses route through the scanner, Send paste, and deeplink path. Ordinary Send → Enter Manually validates the same address and then does not open USDT; Android #1494 at 2057b38 sends that manual entry through its scan handler. Earlier chip-wrapping and address-expansion comments are present in this head as WrappingHStack and the tap-to-expand address.

CI Run Tests passed on this head and does not execute manual-entry navigation. Run Integration Tests was still pending. This review did not rerun tests or start a simulator.

Device testing: not performed in this review.

Findings

  • [MEDIUM] Route bare USDT addresses from Enter Manually — inline at Bitkit/ViewModels/AppViewModel.swift:1325.

Related primary: synonymdev/bitkit-android#1494.

Comment thread Bitkit/ViewModels/AppViewModel.swift

@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 MEDIUM and two LOW findings, inline. Reviewed 87315a3. I reviewed this as a funds and remote-input change: it adds bare-address routing, the send confirmation, and payment-request and subscription endpoints. The MEDIUM and the copy LOW were reproduced on the iPhone 17 simulator, built from this head with the local USDT fixture.

Checked and clean:

  • Send confirmation. Swipe sends quote unchanged (UsdtSendView.swift:634-645). Fee is maximumFee, Max total debit is amount + maximumFee, and Recipient gets is receivedAmount. Moving the bridge amounts into expanded details is the agreed design and is not raised.
  • Bare-address input. usdtValidateRecipient → core parse_address enforces the 0x prefix, length 42, a non-zero address and EIP-55 for mixed case, and it rejects token, OFT and paymaster addresses. No Bitcoin, Lightning or LNURL payload starts with 0x. Hardware scope rejects the address (AppViewModel.swift:1280), and the opt-in prompt still shows when USDT is off (UsdtSendView.swift:112). The scanner and clipboard paths route correctly; only Enter Manually does not (inline).
  • Subscriptions and requests. subscriptionEndpoints(selected:) intersects the selection with availability and asset. The proposal and its pre-send recheck use the same identifiers, an empty selection disables the button, and the service also rejects it. Amount Continue resets the selection only on an asset change, and the sheet-scoped draft resets on reopen.
  • Earn consent. A required claim still gates Approve on the loaded address. approvedUsdtAddress is gated on shareUsdt && isUsdtEnabled, and the relay disclosure stays in relayOriginSection.
  • 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 the new arrow-*-right and plus paths against the exported frame assets, and the removed-chip 50% opacity with +.
    • No deltas apart from the expanded-address LOW inline. The middle truncation of the address is kept deliberately: it shows both ends.
  • Performance. Not performance-relevant: layout and routing only, with no new polling, waits or locks.

Android twin synonymdev/bitkit-android#1494 already routes a bare address from Enter Manually (onAddressContinue → handleScan → isUsdtPaymentInput), so the MEDIUM is iOS-only. The copy LOW applies to both.

Device gate: not run yet — held until the MEDIUM is fixed. J2/J3 need two linked wallets; J1/J4–J7 run against the local USDT fixture.

Comment thread Bitkit/ViewModels/AppViewModel.swift
Comment thread Bitkit/Resources/Localization/en.lproj/Localizable.strings
Comment thread Bitkit/Views/Wallets/UsdtSendView.swift
@ben-kaufman
ben-kaufman force-pushed the feat/usdt-design-followup-20261015 branch from 83565c1 to cce9ade Compare October 15, 2026 14:29
@ben-kaufman

Copy link
Copy Markdown
Contributor Author

Rebased on current master and retained the reviewed USDT fixes. The new receive-refresh screen had a stale QR component call that prevented compilation; it now uses the current edit callback.

The rebased build and all 86 selected tests pass, including receive refresh and manual USDT entry. SwiftFormat passes for all 35 changed Swift files; translation validation reports no errors. Requesting another review on the updated head.

@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: Reviewed the full PR diff against its merge base, at cce9ade.

1 actionable finding — resolve or provide an evidence-backed rebuttal.

The new subscription method field has no initializer default, so the existing PaykitSubscriptionDraft call sites would fail to type-check. Bare-address routing, Earn address sharing, bridge review amounts, and request and subscription endpoint selection were traced in this source. Those contracts were compared with bitkit-android#1494 at 1c37a7e; that is not a review of the Android PR. Android defaults the subscription selection to null, which is what makes an omitted selection mean every available method for the asset.

Earlier comments on Enter Manually, the optional Earn wording, chip wrapping, and the expanded-address divider are addressed in this head.

Validation: tests were not executed in this review. Validate Translations passed on this head. Run Tests and Run Integration Tests were still pending, and the Swift compiler was not available here.

Device testing: not performed in this review.

Findings

  • [HIGH] Default the subscription method selection — inline at Bitkit/Services/PaykitPaymentRequestService.swift:513.

Comment thread Bitkit/Services/PaykitPaymentRequestService.swift
@ben-kaufman

ben-kaufman commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor Author

The E2E build passed on retry on the same commit, including storyboard compilation and app upload. The failure appears to have been transient; no source change was needed. Local E2E builds also passed, including a forced storyboard rebuild. The iOS unit and integration jobs passed; the downstream E2E tests are now queued. Retry run.

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

Code review from our side, no device runs, at cce9ade: one MEDIUM, inline, which is a product call rather than a code bug. Every earlier finding from @jvsena42, @piotr-iohk and Greptile is fixed at this head.

Checked and clean: bare-address routing from scanner, paste, Enter Manually and clipboard (opt-in and hardware-wallet guards intact); the send confirmation's amount, fee and maximum debit; request and subscription method selection enforced in the proposal and the pre-send recheck, with an empty selection blocked and USDT excluded when disabled; Earn approval blocked until the address loads, relay disclosure still on the authorization screen.

Comment thread Bitkit/Resources/Localization/en.lproj/Localizable.strings
@ben-kaufman
ben-kaufman requested a review from ovitrif October 15, 2026 15:52

@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 Bitkit/Views/Wallets/UsdtReceiveView.swift
@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 Bitkit/Views/Subscriptions/CreateSubscriptionView.swift Outdated
@ben-kaufman
ben-kaufman requested a review from jvsena42 October 15, 2026 18:23
@ben-kaufman

Copy link
Copy Markdown
Contributor Author

Mirrored the two journey wording corrections from John's Android device review in f76c499. Both platforms now expect "Not enough USDT to cover the amount and fees." for manually entering the full balance and "Refund in progress" for the pending refund. Checked both against the current strings and error/status mappings; XML and action parity checks pass. Product copy and behavior are unchanged.

@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-review at f76c4998. No HIGH or MEDIUM. All five earlier findings are fixed:

  • MEDIUM, bare 0x in Enter Manually: fixed. SendEnterManuallyView.swift:83 routes 0x to handleSendScan after whitespace is stripped, and testOrdinaryManualEntryRoutesBareAddressToUsdt covers it. A malformed 0x string still fails validation and keeps Continue disabled. Bitcoin, BOLT11 and LNURL input is unaffected, and hardware-wallet Send still rejects 0x.
  • Optional-claim copy: fixed (PubkyAuthApprovalSheet.swift:482-486, pubky_auth__usdt_intro_optional).
  • Expanded-address divider: fixed (UsdtSendView.swift:469-489, SendSectionView.swift:35).
  • Deposit and Choose Recipient floating buttons: fixed (.safeAreaInset in UsdtReceiveView.swift:96-106 and CreateSubscriptionView.swift:47-59).

Also checked and clean:

  • Send: submission logic in UsdtSendView is unchanged; the delta is typography only.
  • Auth approval: consent gating is unchanged.
  • Receive: cce9ade0 is the same onEdit adaptation master got in #947. Expect a one-line @ViewBuilder conflict on the next master merge.

One LOW inline: a journey and the QA doc still describe the old deposit button layout.

Device gate (partial): f76c499 — not run yet. Pending a simulator run of:

  • Enter Manually 0x routing
  • the expanded-address dividers
  • the optional USDT auth claim
  • both floating buttons
    I'll approve once it passes.

Comment thread journeys/usdt-bridge-support.xml Outdated
@ben-kaufman
ben-kaufman requested a review from jvsena42 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.

Approving at 7f904485.

The simulator gate (iPhone 17, local USDT fixture on an Arbitrum fork) ran at f76c4998. 7f904485 only rewords Docs/USDT-QA.md and the deposit-button journey step, and the gate already checked the behaviour that step now describes. All seven paths pass:

  • Enter Manually: a bare 0x address, with or without surrounding spaces, typed or pasted, opens USDT Amount on Arbitrum One. Back twice restores the recipient.
    • A malformed address keeps Continue disabled with the toast.
    • A bcrt1q… address still opens Bitcoin send.
    • With USDT off, Continue shows the enable prompt: Cancel returns quietly, and Enable resumes USDT Amount.
  • Polygon bridge review: the expanded address wraps to two lines and both dividers sit level. Collapse and Hide Details work.
  • Pubky auth:
    • An optional USDT claim shows "You can share…" with the "Share my USDT address" switch, and the switch stays off after Back.
    • The combined claim keeps "Also share…".
    • A USDT-only claim keeps the mandatory copy.
  • Floating buttons: Cross-Network Deposits and Choose Recipient stay pinned, and the content scrolls behind them and clears them at the end, including at accessibility text sizes. On Create Subscription the button stays above the keyboard with the focused field visible.
  • Small screens and sheets: the USDT intro buttons stack at large text. The received celebration's Details and primary buttons work.

One LOW inline on a journey step that asserts the Android error message. Hardware-wallet Send was not run because no hardware wallet was paired.

Device gate: f76c499 — journeys: 5 run (4 partial), 1 failed (usdt-payment-links-and-scans step 18, journey wording, inline); perf: no crash, no hang; Figma: 3 screens compared, 1 delta (compact address middle-truncated, deliberate per earlier review); l10n: English-only, pubky_auth__usdt_intro_optional / pubky_auth__share_usdt not yet translated

Comment thread journeys/usdt-payment-links-and-scans.xml

@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 0ea3fcc into master Oct 15, 2026
18 checks passed
@jvsena42
jvsena42 deleted the feat/usdt-design-followup-20261015 branch October 15, 2026 21:57
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