fix(withdraw): show non-EVM (Tron/Solana) token selection in the selector button#2490
Conversation
Selecting USDT-Tron / USDT+USDC-Solana in the withdraw token drawer updated context but the collapsed button resolved its label via areEvmAddressesEqual, which is always false for base58 addresses — so the button kept reading 'Select a token' and the selection looked like it never happened. Fall back to a case-insensitive literal match (keeping areEvmAddressesEqual for its native-proxy aliasing on EVM tokens).
Code-analysis diffPainscore total: 6242.76 → 6243.14 (+0.38) 🆕 New findings (11)
✅ Resolved (11)
|
🧪 UI test report — ✅ all greenSuites
📊 Coverage (unit)
⏱ 10 slowest test cases
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe crypto withdrawal page now performs missing-amount navigation in an effect, while ChangesWithdraw redirect
Token selection
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
Suggested labels: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
router.push during render is a React violation ('Cannot update Router while
rendering WithdrawCryptoPage') — Next 16's dev overlay hard-errors on any
direct entry or refresh of /withdraw/crypto, which blocked QA of the
non-EVM withdraw flow. Same behavior, one frame later, via useEffect.
|
@coderabbitai review bro |
|
✅ Action performedReview finished.
|
|
@coderabbitai review now pls |
|
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/components/Global/TokenSelector/TokenSelector.tsx`:
- Around line 180-188: Update the token lookup in the selected-token flow around
areEvmAddressesEqual so the fallback compares t.address and selectedTokenAddress
with exact case-sensitive equality. Preserve areEvmAddressesEqual for EVM alias
matching and retain the existing tokenDetails lookup behavior.
🪄 Autofix (Beta)
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 32483471-ddfe-4c32-b76e-33d4ef54d94e
📒 Files selected for processing (2)
src/app/(mobile-ui)/withdraw/crypto/page.tsxsrc/components/Global/TokenSelector/TokenSelector.tsx
|
Review — code quality / DRY / bug risk / security Trivial and safe. The literal fallback is correct: both operands come from the same registry and The render→effect redirect fix is also correct — One note: this bundles two logically-independent fixes (selector label + render-phase-nav) in one PR. Both small and in the same route, disclosed in the description — fine, just flagging. Also: touches |
Base58 is case-significant and both operands come from the same registry — a case-insensitive compare could only mask an upstream case-corruption bug, never fix a legitimate mismatch. areEvmAddressesEqual keeps covering EVM checksum-case variance and native-proxy aliasing.
|
@kushagrasarathe thanks — two updates since your pass: (1) the fallback moved from case-insensitive to exact equality (0a44cd6) per jota + CodeRabbit; your same-source-registry observation is exactly why exact is sufficient, and it additionally keeps the label honest as a canary if any path ever corrupts the selected address's casing. (2) On bundling: agreed it's two logical fixes — kept together because the redirect bug blocked QA of this exact flow; both disclosed in the description. Noted the #2491 overlap (different regions of page.tsx) — whichever merges second rebases. |
kushagrasarathe
left a comment
There was a problem hiding this comment.
APPROVE
Trivial, display-only, and the latest commit improved it beyond my original note.
- The
0a44cd64change from a case-insensitive compare to exact===is strictly more correct: base58 is case-significant and both operands come from the same registry, so a case-insensitive match could only mask an upstream corruption bug, never fix a legit mismatch. Good call. - Native-proxy/checksum aliasing still resolves via
areEvmAddressesEqualfirst — EVM behavior unchanged. - The render→effect redirect fix is correct (
needsAmountRedirectin deps,PeanutLoadingstill renders synchronously, no flash). 209d0114reverted an accidentalsrc/contentsubmodule bump — clean.
CI green apart from the pre-existing repo-wide no-explicit-any eslint failure (unrelated to this PR).
Note for the merge gate: @jjramirezn's earlier CHANGES_REQUESTED is what 0a44cd64 addresses — it still needs their re-review (or dismissal) to unblock, since my approval doesn't clear their request.
Brings in the merged PRs missing from the release: #2490 (token-selector non-EVM label), #2491 (withdraw collateral-charge completion), #2499 (footer legal-entity line). Conflict in withdraw/crypto/page.tsx resolved to keep mobile-release's localization while adopting #2491's fix: pass chargeId into sendMoney so collateral-routed withdraws settle the charge server-side. Re-added the @sentry/nextjs captureMessage import the localization pass had dropped, and adapted crypto-withdraw-confirm.test.tsx to the localized page (context path, next-intl + useFriendlyError mocks). Dropped the dead intentId var (unused on main too).
Summary
Picking USDT-Tron / USDT+USDC-Solana in the withdraw token drawer looked like it did nothing: the tap did select the token (context updates unconditionally, the drawer highlight even shows it), but the collapsed selector button resolves its label via
areEvmAddressesEqual— alwaysfalsefor base58 addresses — so it kept reading "Select a token". Users read that as "the coin can't be selected".One-line fallback to a case-insensitive literal match.
areEvmAddressesEqualstays first for its native-proxy aliasing on EVM tokens (0xeee…↔0x000…).Pairs with peanutprotocol/peanut-api-ts#1230, which unblocks the actual request/charge creation for these destinations (EVM-only schema pattern + base58 case-corruption on storage). Without the BE fix, proceeding past the (now visible) selection still 400s at setup review.
Also fixes a pre-existing React violation hit while QA-ing this flow: the page called
router.push('/withdraw')during render when no amount was set, which hard-errors Next 16's dev overlay on any direct entry/refresh of/withdraw/crypto. The redirect now runs in an effect — same behavior, one frame later.Risks
Display-only. The literal fallback cannot resolve a different token than before: distinct registry tokens never differ only by address case, and native aliasing is still handled by the EVM comparator first.
QA
countryCurrencyMappingsuite failure is unrelated).🤖 Generated with Claude Code
Design notes / adversarial review
selectedTokenDataderivation → CTA →onReview): selection state always worked (handler unconditional; Sentry payloads prove base58 reached the BE); the collapsed-button label was the only broken link. No auto-reset effect exists that could clear the selection.areEvmAddressesEqual; for base58 the registry is the single source, so exact equality is both sufficient and a canary for any future case corruption in the selection path.Summary by CodeRabbit