Skip to content

fix(errors): show friendly message when wallet rejects order signing - #7781

Merged
elena-zh merged 4 commits into
cowprotocol:developfrom
tenderdeve:fix/7774-signing-reject-error
Jul 7, 2026
Merged

elena-zh merged 4 commits into
cowprotocol:developfrom
tenderdeve:fix/7774-signing-reject-error

Conversation

@tenderdeve

@tenderdeve tenderdeve commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #7774

When a Safe/WalletConnect wallet rejects the order-signing request, viem wraps the rejection in a TransactionExecutionError whose top-level shortMessage is "An unknown RPC error occurred.". The real 4001 code and "User rejected" message only live on error.cause.

isRejectRequestProviderError only looked at the top-level error, so those rejections missed detection and getSwapErrorMessage surfaced the raw "An unknown RPC error" instead of "User rejected signing the order".

Now it walks the error.cause chain (depth-capped against cyclic causes), the same recursive approach the TWAP flow already uses. Fixes it once for every flow that relies on the util — swap, limit, eth, approval.

Added libs/common-utils/src/misc.test.ts covering the top-level code/message cases, the nested-cause case from the report, non-rejection errors, and the cyclic-cause guard.

Summary by CodeRabbit

  • Bug Fixes

    • Improved detection of rejected provider requests, including standard user-rejection codes and common wallet-specific messages.
    • Made nested error “cause” inspection safer by limiting how deep recursion can go and avoiding infinite loops with cyclic cause chains.
    • Ensured non-rejection inputs (such as null/undefined) reliably return false.
  • Tests

    • Added a new test suite covering standard rejection codes, wallet-specific messages, nested/varied cause shapes, null/undefined inputs, and cyclic cause chains.

Safe/WalletConnect wallets (via viem) wrap a user's signing rejection in a
TransactionExecutionError whose top-level shortMessage is "An unknown RPC
error occurred."; the real 4001 code and "User rejected" message only live on
error.cause. isRejectRequestProviderError only inspected the top-level error,
so these rejections fell through to getSwapErrorMessage's generic branch and
surfaced the raw "An unknown RPC error" to the user instead of "User rejected
signing the order".

Walk the error.cause chain (depth-capped to guard against cyclic causes),
mirroring the recursive detection the TWAP flow already uses. Every consumer
(swap, limit, eth, approval) now maps the wrapped rejection correctly.
@vercel

vercel Bot commented Jul 1, 2026

Copy link
Copy Markdown

@tenderdeve is attempting to deploy a commit to the cow-dev Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jul 1, 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0f377b7e-3805-4ac9-822f-93935979f226

📥 Commits

Reviewing files that changed from the base of the PR and between e4df9a8 and d89e472.

📒 Files selected for processing (1)
  • libs/common-utils/src/misc.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • libs/common-utils/src/misc.ts

Walkthrough

Updates isRejectRequestProviderError to inspect nested error.cause chains with a depth cap, and adds tests for direct, nested, non-rejection, and cyclic error cases.

Changes

Rejection Detection Recursion

Layer / File(s) Summary
Recursive depth-guarded cause inspection
libs/common-utils/src/misc.ts
Adds MAX_ERROR_CAUSE_DEPTH = 8, a depth parameter, early exits for falsy or too-deep errors, and recursive cause inspection.
Tests for rejection detection scenarios
libs/common-utils/src/misc.test.ts
Adds coverage for standard rejection codes, wallet-specific messages, nested cause chains, non-rejection inputs, and cyclic cause handling.

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

Possibly related PRs

Suggested labels: Viem migration

Suggested reviewers: shoom3301, elena-zh

Poem

A rabbit peeks down error holes,
Counts causes, hops, and tangled shoals.
Eight steps deep, then stop the chase —
No endless loop can win this race.
Rejection found, the path runs clear 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main fix: showing a friendly message when wallet order-signing is rejected.
Description check ✅ Passed The description explains the fix, links the issue, and covers behavior and tests, though it omits the template's To Test and screenshot sections.
Linked Issues check ✅ Passed The changes address #7774 by detecting wallet rejections through nested error.cause chains and adding tests for the reported and edge cases.
Out of Scope Changes check ✅ Passed The PR stays focused on the error utility and its tests, with no clear unrelated code changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
libs/common-utils/src/misc.ts (1)

186-188: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

any usage violates the no-any guideline.

error: any is explicitly disallowed for production code, even though it's flagged with a TODO/eslint-disable. Consider typing as unknown and narrowing (typeof error === 'object' && error !== null) similar to getProviderErrorMessage, to avoid unchecked property access on error.code/error.cause.

As per coding guidelines, "MUST NOT use any or non-null assertions (!) in production code."

🤖 Prompt for 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.

In `@libs/common-utils/src/misc.ts` around lines 186 - 188, The
`isRejectRequestProviderError` helper still uses `error: any`, which violates
the no-`any` guideline. Change the `error` parameter to `unknown` and narrow it
before accessing `code` or `cause`, following the same object-check pattern used
in `getProviderErrorMessage`. Remove the `@typescript-eslint/no-explicit-any`
suppression and keep the recursive `depth` logic intact.

Source: Coding guidelines

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

Nitpick comments:
In `@libs/common-utils/src/misc.ts`:
- Around line 186-188: The `isRejectRequestProviderError` helper still uses
`error: any`, which violates the no-`any` guideline. Change the `error`
parameter to `unknown` and narrow it before accessing `code` or `cause`,
following the same object-check pattern used in `getProviderErrorMessage`.
Remove the `@typescript-eslint/no-explicit-any` suppression and keep the
recursive `depth` logic intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ca7d40b8-4dd0-4c94-a250-c85a7c65771c

📥 Commits

Reviewing files that changed from the base of the PR and between d5abb10 and e4df9a8.

📒 Files selected for processing (2)
  • libs/common-utils/src/misc.test.ts
  • libs/common-utils/src/misc.ts

@elena-zh elena-zh added the trigger-preview Add to a fork PR to trigger CF-pages preview. See https://github.com/cowprotocol/cowswap/pull/7615 label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Cloudflare Pages preview mirror

Preview branch URL: https://github.com/cowprotocol/cowswap/tree/cf-preview/pr-7781
Mirror PR: #7787
Cloudflare Pages preview links will be posted on the mirror PR by the Cloudflare Pages GitHub integration once builds complete.

Source fork branch: tenderdeve/cowswap:fix/7774-signing-reject-error
Approval target SHA: 5e534e527043
Last mirrored SHA: e4df9a80ee80
Last comment update: @fairlighteth at 2026-07-07T09:24:18.155Z

  • Sync Cloudflare preview to approval target commit

@github-actions github-actions Bot removed the trigger-preview Add to a fork PR to trigger CF-pages preview. See https://github.com/cowprotocol/cowswap/pull/7615 label Jul 1, 2026
@vercel
vercel Bot temporarily deployed to Preview – storybook July 1, 2026 11:50 Inactive
@vercel
vercel Bot temporarily deployed to Preview – widget-configurator July 1, 2026 11:50 Inactive
@vercel
vercel Bot temporarily deployed to Preview – cowfi July 1, 2026 11:51 Inactive

@elena-zh elena-zh left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM, thanks

@elena-zh
elena-zh requested review from Danziger and fairlighteth July 1, 2026 13:13

@fairlighteth fairlighteth left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ AI Review (Codex GPT-5, worked 4m): no new non-duplicate findings

Review completed. I found no new non-duplicate comments worth posting.

Review scope and related context
  • Checked libs/common-utils/src/misc.ts and libs/common-utils/src/misc.test.ts against origin/develop...origin/pr/7781.
  • The PR matches the linked Safe/WalletConnect rejection issue and adds focused coverage for direct, nested, non-rejection, null/undefined, and direct cyclic cause cases.
  • Existing CodeRabbit feedback already covers the still-valid root AGENTS.md issue: error: any in isRejectRequestProviderError at libs/common-utils/src/misc.ts:188. I’m not duplicating that.
  • No active review threads were returned; the PR already has one human approval.

Generated using the pr-review skill from the CoW Protocol skills repo.

@fairlighteth
fairlighteth self-requested a review July 7, 2026 09:23
@elena-zh
elena-zh enabled auto-merge (squash) July 7, 2026 09:28
@elena-zh
elena-zh merged commit a396982 into cowprotocol:develop Jul 7, 2026
12 of 20 checks passed
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show a better error when cancel order signing request

3 participants