Skip to content

chore(rn-cli-wallet): apply UX writing guidelines audit fixes#512

Open
ignaciosantise wants to merge 2 commits into
mainfrom
chore/audit-rn-cli-wallet-copy
Open

chore(rn-cli-wallet): apply UX writing guidelines audit fixes#512
ignaciosantise wants to merge 2 commits into
mainfrom
chore/audit-rn-cli-wallet-copy

Conversation

@ignaciosantise
Copy link
Copy Markdown
Collaborator

Summary

Aligns the React Native CLI sample wallet's user-facing copy with the WalletConnect UX Writing Guidelines (v2.0). Companion change to #507 (pos-app), scoped to wallets/rn_cli_wallet.

Per-product calls (out of scope, kept as-is):

  • Wallet still says Sign (the wallet is the signer — §6 "Confirm not Sign" applies to WCPay product surfaces, not the wallet itself)
  • Dev-only labels left untouched: Client ID, Socket status, App version, Read logs, Methods, Events, log row format
  • All-caps chain headers replaced with proper-noun casing (Ethereum / Sui / Ton / Tron / Canton / Solana)

What changed (33 src files + versionCode)

Payment flow (§5 / §4.8)

  • Gas feeNetwork fee across ReviewPaymentView, GasFeeView (title, body, label)
  • Payment-error titles + bodies now state whether funds moved and give a next step: e.g. "Transaction failed""Payment didn't go through. No funds were moved. Try again, or pay with a different asset."
  • "Not enough funds""Not enough funds in your wallet" with asset-aware body
  • "Select a token to pay with""Choose the asset you want to pay with" (list spans native + ERC-20-style assets)

Loading anti-patterns (§4.6)

  • "Loading..." / "Loading balances..." → specific copy with ellipsis
  • "Processing your payment...""Confirming your payment…"

Errors with next steps (§4.8)

  • Session modal toasts: "Signature failed" / "Transaction failed" / "Authentication failed" / "Rejection failed" / "Validation failed" / "Send message failed""Couldn't sign message" / "Couldn't send transaction" / "Couldn't authenticate" / "Couldn't reject request" / "Couldn't validate request" / "Couldn't send message" (bodies still carry error.message)
  • Scanner: "No URL found in clipboard" / "Failed to read clipboard" rewritten with recovery hints
  • Camera: "Camera not available""Camera unavailable. Enable camera access in Settings."
  • WebView: "Failed to load the form""Couldn't load the form. Check your connection, then try again."

Empty states (§4.5)

  • Connections empty state gains a Scan QR code CTA so it matches the Headline → Body → CTA pattern

Capitalization & punctuation (§7)

  • Sentence case across nav (Connected AppsConnected apps), settings (Secret Keys & Phrases, Import Wallet), modal titles, Ton modal section headers (Sign with AddressSigning address, Transaction Details → sentence case), and Scan instruction
  • Exclamation marks removed: "Got it!""Got it", "{Chain} wallet imported!""{Chain} wallet added"
  • Em dash removed from InfoExplainerView; body rewritten in active voice and shortened to fit §8 modal-body target
  • All-caps chain headers in SecretPhrase + ImportWalletModal segmented control → proper-noun casing

Misc

  • SessionSignCantonModal approveLabel "Approve""Sign" (consistency with other chains)
  • Settings clipboard toast now labels the value ("Client ID copied" instead of generic "Value copied to clipboard")
  • Android versionCode bumped 68 → 69 (per AGENTS.md)

Things deliberately not touched

  • Sign CTA + "Sign a message for…" modal titles (kept by design call)
  • ExpiryWarningView CTA Complete payment — leaving as-is because piping the amount into that view requires prop plumbing through the parent; can be a follow-up
  • Dev-only LogList rows, Client ID, Socket status, Methods, Events
  • wallets/rn_cli_wallet/ios/Podfile.lock (unrelated yarn install side-effect)

Test plan

  • yarn tsc --noEmit clean (verified locally)
  • yarn lint shows no new errors/warnings (pre-existing unused-_ in SessionSignCantonModal:55 and a react/no-unstable-nested-components warning in RootStackNavigator — both untouched by this PR)
  • Sanity-check the Pay flow (success, insufficient_funds, expired, generic error) so the new titles + bodies render
  • Sanity-check Connections empty state CTA opens ScannerOptionsModal
  • Sanity-check Import wallet flow on all 6 chains (segmented control now displays Ethereum / Ton / Tron / Sui / Canton / Solana)
  • Eyeball the SecretPhrase screen for proper-noun casing
  • Maestro E2E run (pay flows still use the same testIDs)

🤖 Generated with Claude Code

Aligns the React Native CLI sample wallet's user-facing copy with the
WalletConnect UX Writing Guidelines (v2.0). Per-product calls:

- Sign / Approve language kept (wallet surface is the signer)
- Dev-only labels left as-is (Client ID, Socket status, logs)
- All-caps chain headers replaced with proper-noun casing

Highlights:
- Gas → Network fee across the WalletConnect Pay review/explainer
- Payment-error states now say whether funds moved + give next steps
- Loading anti-patterns ("Loading...") replaced with specific copy
- Session modal failure toasts get specific titles + recovery hints
- Empty Connections state gets a "Scan QR code" CTA
- Sentence case across nav, settings, and modal headers
- Exclamation marks removed from CTAs and toasts
- "Token" → "Asset" on the payment picker
- "EVM/SUI/TON/TRON/CANTON/SOLANA" → "Ethereum/Sui/Ton/Tron/Canton/Solana"

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 28, 2026 18:56
@vercel
Copy link
Copy Markdown

vercel Bot commented May 28, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
pos-demo Ready Ready Preview, Comment May 29, 2026 2:31pm

Request Review

@claude
Copy link
Copy Markdown

claude Bot commented May 28, 2026

Claude finished @ignaciosantise's task in 4m 17s —— View job


PR Review

  • Gather context and read CLAUDE.md
  • Read changed files for review
  • Run license compliance subagent → ✅ No issues
  • Run breaking changes subagent → ✅ No issues
  • Run data classification subagent → ✅ No issues
  • Consolidate findings and post final review

🚨 PR Too Large
Files: 34 Lines: 275 Severity: HIGH Category: maintainability
34 files exceed the 15-file threshold. That said, all changes are homogeneous copy updates with no logic, so splitting would produce pure churn. This flag is informational only for this PR type.

Found 2 issue(s)

Issue 1: Generic error fallback body shown for all error types in ResultView

ID: resultview-defaultmessage-errortypes-a3c1
File: wallets/rn_cli_wallet/src/modals/PaymentOptionsModal/ResultView.tsx:63
Severity: LOW
Category: code_quality

Context:

  • Pattern: defaultMessage for the error state is 'Payment didn't go through. No funds were moved. Try again, or pay with a different asset.' This is used as the body fallback ({message || defaultMessage}) for all error types — including insufficient_funds, expired, and cancelled.
  • Risk: If message is ever not passed (e.g., future caller omits it), insufficient_funds would show "No funds were moved" in the body while the title says "Not enough funds in your wallet" — inconsistent. For expired/cancelled, "No funds were moved" is accurate but gives wrong recovery action (doesn't say to ask merchant).
  • Impact: Wrong recovery guidance for some error states when message prop is absent.
  • Trigger: Parent forgets to pass message; or a new error path renders ResultView without the prop.

Recommendation: Derive the default body from getErrorMessage to keep title/body consistent by error type:

const defaultMessage = isSuccess
  ? 'Payment confirmed'
  : errorType
    ? getErrorMessage(errorType)
    : 'Payment didn't go through. No funds were moved. Try again, or pay with a different asset.';

Issue 2: Redundant toast copy for Solana base58 secret key section

ID: secretphrase-solana-toast-redundant-b8f2
File: wallets/rn_cli_wallet/src/screens/SecretPhrase/index.tsx:32
Severity: LOW
Category: code_quality

Context:

  • Pattern: SecretSection copies to clipboard and shows text1: \${title} secret copied`. For the section with title="Solana (base58 secret key)"`, the toast reads "Solana (base58 secret key) secret copied" — "secret key secret copied" is redundant.
  • Risk: None functional, but awkward on the dev-only Secret Phrase screen.
  • Impact: Cosmetic only; dev screen.
  • Trigger: Tapping copy on the Solana base58 section.

Recommendation: Shorten the title to "Solana (base58)" or adjust the toast to avoid doubling "secret":

// Option A: change title

// Option B: smarter toast
text1: title.toLowerCase().includes('secret') ? `${title} copied` : `${title} secret copied`

License compliance: ✅ No issues — build.gradle change is a versionCode bump only (68→69), no new dependencies.

Breaking changes: ✅ No public API changes. The CHAIN_OPTIONS rename ('EVM''Ethereum' etc.) is internal to the modal; no persisted state or exported types affected.

Data classification: ✅ No new sensitive data exposure. error.message in toast text2 fields was pre-existing.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

…llet-copy

# Conflicts:
#	wallets/rn_cli_wallet/src/modals/LoadingModal.tsx
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