Repository navigation
fix: copy and share USDT receiving addresses - #1558
Conversation
[Medium impact] The changes reach the USDT receive and Android sharing flow. The PR appears safe to merge, with a non-blocking timing issue in the new share test. Findings
SummaryUSDT receiving now copies plain addresses while keeping payment details in the QR.
Diagram%%{init: {'theme': 'neutral'}}%%
flowchart LR
A[Selected receive address and amount] --> B[USDT receive view]
B --> C[Copy plain address]
B --> D[Share network, address and amount]
A --> E[Payment URI]
E --> F[QR image]
F --> D
Reviews (1) · Last reviewed commit: "fix: copy and share usdt receiving addre..." · Reviewed by Greptile |
talosmachina
left a comment
There was a problem hiding this comment.
No findings. On the USDT receive screen, Copy and a tap on the QR now copy the plain receiving address (the selected network's deposit address included). Share, from the QR and from Show Details, sends the network, the address, the optional requested amount and a QR image that still encodes the payment URI. Reviewed aba0c43, full tier, reasoned from the code and CI (the branch was not built on this reviewer's host).
What I checked, and 5 candidates I ruled out
Read in full: UsdtReceiveContent.kt, UsdtDepositReceiveScreen.kt, UsdtReceiveAmountContent.kt, the ReceiveQrView and CopyAddressCard parts of ReceiveQrScreen.kt, rememberQrBitmap in QrCodeImage.kt, ShareSheet.kt, UsdtReceivePrivacyTest.kt
Call sites traced: CopyAddressCard (the five ReceiveQrScreen.kt callers pass no shareQrContent, so Share stays enabled and text-only for them), UsdtReceiveContent (one caller)
CI: detect-changes and e2e-branch determine green; build, build-local and lint still running at review time on this head (lint, detekt and build-local were green on the previous head 98bda61)
Ruled out
- Deposit share amount disagrees with the deposit QR: the text uses
usdtFormatAmount(state.address.amount), and bitkit-core'sreceiverejects a response whoseamountdiffers from the request, so it matches theuint256instate.address.uri. - Trailing-dot amount reaching the text (
3. USDT): Continue is gated onPaykitAmount.parse, whose regex refuses a trailing separator, so such an amount never becomesamount. - Details Share firing before the QR bitmap exists and sending text only: the button is disabled until
shareBitmapis non-null whenevershareQrContentis set. - Stale bitmap after a network or amount change:
rememberQrBitmapis keyed oncontentand resets to null on change, which disables Share until the new image is ready. - Tap on the QR still copies the URI:
ReceiveQrViewpassescopyContent = copyTextto the QR, nowaddress; the test asserts the clipboard after both the QR tap andReceiveCopyQR.
Merge confidence: 4/5, the build and lint jobs had not finished on this head at review time and the change was reasoned, not run.
Regtest APKDownload bitkit-dev-debug universal APK (expires in 30 days). |
There was a problem hiding this comment.
Verdict: ✅ Approve. I found no defects, and all three cases passed on device at aba0c43.
Findings: none.
QA for aba0c43: an Android 16 emulator (Pixel 7) on a local USDT stack (Arbitrum fork, bundler and a mock bridge provider).
- I read each copy back from Android's clipboard editor, which opens from the preview the system shows after a new copy.
- What a QR encodes comes from its content description on screen.
- I checked each Share from the chooser's text preview, and by decoding the PNG it attached.
Test 1: Arbitrum receive with 3.5 USDT ✅ Copy, a QR tap and Details Copy hold only the address. Both Shares send the network, the address, 3.5 USDT and a QR of the payment URI.
- The QR encodes
ethereum:0xFd08…@42161/transfer?address=0xB862…d1B7&uint256=3500000. - Each of these put only
0xB8625FaAC7a8C387286cef42c7534074c4E5d1B7on the clipboard:- Copy.
- A tap on the QR.
- Copy in Show Details.
- Share on the QR and Share in Show Details each sent an image with "Network: Arbitrum One", the address and "3.5 USDT". Both images decode to the payment URI with
uint256=3500000.
test1-arbitrum-3.5-usdt.2x.mp4
Test 2: Arbitrum receive without an amount, and Back ✅ Every copy holds the address while the QR keeps the full URI, and both Backs behave as the journey says.
- Show Details shows
0xB862…d1B7, and its Copy holds only that address. - System Back from Show Details returns to the QR.
- Its Copy and a tap on it hold the same address.
- The QR encodes the full URI, with the Arbitrum USDT token and chain 42161.
- Share sends "Network: Arbitrum One" and the address with no amount line. The image decodes to the same URI.
- Back from the QR closes Receive onto the USDT wallet without switching to Savings.
test2-arbitrum-no-amount.2x.mp4
Test 3: Polygon deposit of 3.5 USDT, then back to Arbitrum ✅ Copies and Shares use the Polygon deposit address. After the switch back, they use the wallet address with no leftover amount.
- After the deposit was prepared, the QR encodes
ethereum:0xc213…8e8f@137/transfer?address=0x3e91…575e.- The deposit QR carries no
uint256, so the amount appears in the share text only.
- The deposit QR carries no
- Copy, a QR tap and Details Copy each hold
0x3e91771f24Bc9B1AbecdD8c128cdD99e912a575e, not the wallet address. - Both Shares sent "Network: Polygon", the deposit address and "3.5 USDT". Both images decode to the Polygon URI.
- Back on Arbitrum One:
- Every copy holds
0xB862…d1B7. - Both Shares send "Network: Arbitrum One" and the address, with no amount.
- Both images decode to the Arbitrum URI.
- Every copy holds
test3-polygon-then-arbitrum.2x.mp4
Scope: a full review of 722c824..aba0c43 (9 files). The cases drove every changed app path. The other ReceiveQrView and CopyAddressCard callers (Bitcoin, Lightning, hardware wallet) keep shareQrContent = null; I checked this in the code.
Pair PR synonymdev/bitkit-ios#997 at 1294b7e makes the same change, so it matches:
- The QR tap and Copy copy the plain address.
- Share sends the same text.
- Both Shares attach a QR image.
jvsena42
left a comment
There was a problem hiding this comment.
Approving at aba0c437f with one LOW open inline. Fix it here or in a follow-up issue, your choice; reply on the thread saying which, with the issue link if it is a follow-up.
Checked and clean:
- Copy, a QR tap and Details Copy all copy
state.address?.address ?: wallet.address, the address shown in Details, and the QR encodesstate.address?.uri ?: urifrom the same source.UsdtReporesets the state with an emptyreceiveUrion an address change, so the two cannot drift. - Changing network clears
amount/draftAmountand nulls the address. Edit on a deposit re-selects the network, and Back lands on Arbitrum with no amount. - Details Share stays disabled until
rememberQrBitmap(keyed on content) has the image. - Bitcoin, Lightning and hardware-wallet
CopyAddressCardcallers pass noshareQrContent, so their Share stays enabled and text-only.ReceiveQrViewis unchanged. - The journeys and
docs/usdt-qa.mdmatch the new behaviour and are byte-identical to synonymdev/bitkit-ios#997. - greptile's QR-share wait in
UsdtReceivePrivacyTestholds:fetchSemanticsNodes()idles through the 200 ms Crossfade, so the fading image is never matched. 15 consecutive runs on an emulator passed, and a probe that blocked QR encoding never matched early.
CI is green at this head.
Device gate: aba0c43 — Savings receive on the CI APK (bitkit-dev-debug-190-universal.apk), new wallet, with and without a 5,000-sat amount: QR Copy and a QR tap copy the address, or the BIP21 when it carries an amount; QR Share attaches the image with the same text; Details Copy copies the BIP21 without lightning, as master does; Details Share is text-only and enabled. All passed. USDT 3.50 share: see the LOW.
Skipped — already driven this round: Arbitrum receive with and without an amount, Show Details Copy and Share, and the Polygon deposit and return to Arbitrum. These are the changed actions of usdt-receive-amount-and-units.xml and usdt-wallet-navigation.xml (Android 16, by ovi-reviewer at aba0c43, passed: #1558 (review)).
Skipped — covered by CI at aba0c43: unit tests, detekt, lint, local e2e (all green).
perf: not relevant; l10n: no UI text changed (the share text reuses usdt__receive_network).
Fixes #1556
This PR makes USDT receive copying and sharing work with exchanges and plain address fields.
Description
Out of Scope
Design
USDT receive flow. Existing layout and styling are unchanged; copy/share behavior follows #1556 and the agreed receive-sharing requirements.
Preview
Copy:
0x…Shared text:
The attached QR retains the payment URI and
uint256=3500000.QA Notes
Journeys
usdt-receive-amount-and-units.xml— plain-address copying, exact requested amount, network label and payment QR sharing from both views.usdt-wallet-navigation.xml— the receive QR copies its address while retaining the payment URI for scanning.Manual Tests
Automated Checks
UsdtReceivePrivacyTest.kt— checks QR taps, both Copy buttons, both Share actions and decodes the actual shared image while changing amounts and selected receive addresses.UsdtReceivePrivacyTest.kton an API 36 emulator — both tests passed, including direct/Polygon/direct transitions and exact six-decimal amounts.