Skip to content

fix(withdraw): map Rhino NoRouteFoundError to actionable route-not-found copy - #2656

Draft
abalinda wants to merge 1 commit into
mainfrom
hotfix/rhino-route-not-found-copy
Draft

fix(withdraw): map Rhino NoRouteFoundError to actionable route-not-found copy#2656
abalinda wants to merge 1 commit into
mainfrom
hotfix/rhino-route-not-found-copy

Conversation

@abalinda

@abalinda abalinda commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Companion to peanut-api-ts#1320 (TASK-21284). When Rhino cannot route a pair, the backend surfaces the provider tag (NoRouteFoundError) verbatim and the withdraw confirm screen shows the raw string. Map it to ROUTE_NOT_FOUND_ERROR in the shared calculate() catch, so all three consumers (withdraw, pay-request, claim-xchain) inherit the copy the Confirm view already special-cases — its Retry button calls onBack() for this constant, which returns the user to the amount input. No new UI code; one mapping line plus the hook's first test file.

Task

Notion TASK-21284 — Fix Solana USDC withdrawal preview failure (DoD bullet 2: unsupported routes show a specific error and leave the user able to correct the input).

Risks / breaking changes

  • None cross-repo. Substring match on the thrown message; every other error passes through verbatim (pinned by test).
  • Independent of api#1320 deploy order — before it, previews fail with the api-side message either way; after it, unroutable pairs get the actionable copy.

QA

  • New useCrossChainTransfer.test.ts: NoRouteFoundError → ROUTE_NOT_FOUND_ERROR; any other message passes through verbatim.
  • Full local gate: typecheck clean, 226 suites / 2889 tests green.

Screenshots: N/A (no new surface — the existing ErrorAlert renders different copy on an error path that today shows a raw provider string).

Design notes / accepted trade-offs

  • /code-review medium (1 finding, applied-as-follow-up): the ROUTE_NOT_FOUND_ERROR English constant bypasses the classifyError/next-intl localization path. Pre-existing pattern (same constant + equality check in Confirm.withdraw.view.tsx and Claim/Link/Initial.view.tsx before this PR); migrating it to a FriendlyErrorCode touches the Confirm view's error === ROUTE_NOT_FOUND_ERROR special-case, so it goes in a separate localization follow-up rather than this hotfix. No behavior regression — users previously saw a raw JSON blob.

Summary by CodeRabbit

  • Bug Fixes
    • Improved cross-chain transfer error handling by showing a clear route-not-found message when no transfer route is available.
    • Preserved the original error details for other preview and fee-estimation failures.
    • Enabled the appropriate fee-estimation error state when a route cannot be found.

…und copy

When Rhino can't route a pair, the backend surfaces the provider tag
verbatim and the confirm screen showed the raw string. Map it to
ROUTE_NOT_FOUND_ERROR in the shared calculate() catch so all three
consumers (withdraw, pay-request, claim-xchain) inherit the copy the
Confirm view already special-cases (Retry sends the user back to fix
the input). Follow-up to api#1320 (TASK-21284).
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
peanut-wallet Ready Ready Preview Aug 10, 2026 3:33pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1ffc7ca1-4d4b-45f8-8e3e-7cd7edc8e7e6

📥 Commits

Reviewing files that changed from the base of the PR and between 11601d0 and 8d085b5.

📒 Files selected for processing (2)
  • src/features/payments/shared/hooks/useCrossChainTransfer.test.ts
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts

📝 Walkthrough

Walkthrough

The cross-chain transfer hook now maps NoRouteFoundError to ROUTE_NOT_FOUND_ERROR. Other calculation errors retain their original messages. Tests cover both behaviors.

Changes

Cross-chain error handling

Layer / File(s) Summary
Error mapping and validation
src/features/payments/shared/hooks/useCrossChainTransfer.ts, src/features/payments/shared/hooks/useCrossChainTransfer.test.ts
The calculation path normalizes NoRouteFoundError to ROUTE_NOT_FOUND_ERROR. Tests verify route-not-found handling and preservation of unrelated preview errors.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: hugo0

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: mapping Rhino NoRouteFoundError to actionable route-not-found copy.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch hotfix/rhino-route-not-found-copy

Comment @coderabbitai help to get the list of available commands.

@abalinda

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Review rate limited.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions

Copy link
Copy Markdown
Contributor

Code-analysis diff

Painscore total: 7141.56 → 7141.78 (+0.22)
Findings: 0 net (+8 new, -8 resolved)

🆕 New findings (8)

  • high complexity — src/features/payments/shared/hooks/useCrossChainTransfer.ts — CC 34, MI 45.78, SLOC 332
  • medium high-dlt — src/features/payments/shared/hooks/useCrossChainTransfer.ts:173 — useCrossChainTransfer: DLT 35 (calls 35 distinct functions — high context load)
  • medium high-mdd — src/features/payments/shared/hooks/useCrossChainTransfer.ts:173 — useCrossChainTransfer: MDD 30.6 (uses across many lines from declarations)
  • medium high-mdd — src/features/payments/shared/hooks/useCrossChainTransfer.ts:421 — runBridgePath: MDD 26.7 (uses across many lines from declarations)
  • low high-dlt — src/features/payments/shared/hooks/useCrossChainTransfer.ts:234 — : DLT 25 (calls 25 distinct functions — high context load)
  • low high-mdd — src/features/payments/shared/hooks/useCrossChainTransfer.ts:234 — : MDD 17.2 (uses across many lines from declarations)
  • low high-mdd — src/features/payments/shared/hooks/useCrossChainTransfer.ts:535 — buildSameChainTx: MDD 17.0 (uses across many lines from declarations)
  • low high-dlt — src/features/payments/shared/hooks/useCrossChainTransfer.ts:191 — : DLT 16 (calls 16 distinct functions — high context load)

✅ Resolved (8)

  • src/features/payments/shared/hooks/useCrossChainTransfer.ts — CC 33, MI 45.85, SLOC 330
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:172 — useCrossChainTransfer: DLT 34 (calls 34 distinct functions — high context load)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:172 — useCrossChainTransfer: MDD 31.2 (uses across many lines from declarations)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:415 — runBridgePath: MDD 26.7 (uses across many lines from declarations)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:233 — : DLT 24 (calls 24 distinct functions — high context load)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:233 — : MDD 17.9 (uses across many lines from declarations)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:529 — buildSameChainTx: MDD 17.0 (uses across many lines from declarations)
  • src/features/payments/shared/hooks/useCrossChainTransfer.ts:190 — : DLT 16 (calls 16 distinct functions — high context load)

@github-actions

Copy link
Copy Markdown
Contributor

🧪 UI test report — ✅ all green

Suites

  • unit: 2892 ran, 0 failed, 0 skipped, 50.9s

📊 Coverage (unit)

metric %
statements 65.8%
branches 50.8%
functions 55.9%
lines 66.5%
⏱ 10 slowest test cases
time test
3.9s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › never places two stickers in heavy overlap (broad seed sweep)
1.2s src/utils/__tests__/demo-api.test.ts › isDemoMode() is false when not running under Capacitor
0.5s src/app/actions/__tests__/api-headers.test.ts › should include Content-Type in validateInviteCode
0.5s src/services/__tests__/resolveClaimLink.test.ts › restores the pristine password after a redirect mangles the fragment
0.5s src/components/Card/share-asset/__tests__/shareAssetLayout.test.ts › every sticker stays within canvas at any count
0.3s src/app/actions/__tests__/api-headers-extended.test.ts › should not include apiKey in validateInviteCode body
0.3s src/utils/__tests__/sentry.utils.test.ts › defaults to the client budget under a browser global
0.3s src/utils/__tests__/auth-token.test.ts › is none — never guarded — when only the guarded marker is present
0.3s src/utils/__tests__/auth-token.test.ts › ignores the guarded marker and falls back to the plain token
0.3s src/utils/__tests__/auth-token.test.ts › authReady does not park — hydrates the plain token without an unlock
📍 Inline annotations are in the **Unit test report** check above. Coverage artifact: `coverage-unit`. Generated by `.github/workflows/tests.yml`.

@abalinda

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

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.

1 participant