Skip to content

fix(swapper): classify Relay insufficient funds and Thornode HTTP-error responses#12365

Merged
kaladinlight merged 1 commit into
developfrom
fix/swapper-quote-error-classification
May 20, 2026
Merged

fix(swapper): classify Relay insufficient funds and Thornode HTTP-error responses#12365
kaladinlight merged 1 commit into
developfrom
fix/swapper-quote-error-classification

Conversation

@kaladinlight
Copy link
Copy Markdown
Member

@kaladinlight kaladinlight commented May 20, 2026

Description

Two swapper error-classification fixes so users see useful messages instead of "An error occurred getting a quote":

  • Relay InsufficientFunds previously mapped to SellAmountBelowTradeFee, surfacing "sell amount does not cover fee" when the wallet simply didn't have the funds. Adds a new TradeQuoteError.InsufficientFunds, routes Relay's error code to it, handles it in validateTradeQuote's switch (which otherwise hits assertUnreachable and throws), adds it to SWAPPER_USER_ERRORS so the quote stays in the available list, and maps it to common.insufficientFundsForTrade.
  • Thornode 4xx responses were lost because getQuote only inspected the success-shape { error } body. The 4xx body uses the same { error: string } shape but lands on cause.response.data after axios rejects, so we now read it from there (typed via AxiosError<ThornodeResponseError>) and run the same pattern matching. "trading is halted" now surfaces as TradeQuoteError.TradingHalted. Any unmapped Thornode error message is forwarded as UnknownError instead of falling through to the generic QueryFailed.

Issue (if applicable)

closes #

Risk

What protocols, transaction types, wallets or contract interactions might be affected by this PR?

Low. Touches error-classification paths only — no changes to quote pricing, transaction construction, or signing. Affected swappers: Relay (one error mapping), Thornode/Mayachain (error-message extraction in shared getQuote helper). Unmatched errors still fall through to the previous behavior.

Testing

Engineering

  • Relay path: trigger a Relay quote with insufficient sell-asset balance (e.g. select an amount above wallet balance for a Relay-supported pair). Quote should appear in the available list with "Insufficient funds for trade" instead of disappearing or showing the fee message.
  • Thornode path: hit any Thornode pair whose pool is currently halted. The 400 response body looks like {"error":"{\"code\":3,\"message\":\"... trading is halted ...\"}"}. The quote should surface as "Trading is not currently active" instead of "An error occurred getting a quote".
  • Regression: existing 2xx-with-{ error } Thornode error paths (e.g. "not enough fee", "not enough to pay transaction fee") should continue to map to createTradeAmountTooSmallErr.

Operations

  • 🏁 My feature is behind a flag and doesn't require operations testing (yet)

User-facing impact is limited to two error-message strings becoming more accurate. Regression check: confirm normal Relay and Thornode quotes still load and execute.

Screenshots (if applicable)

insufficientfunds image

🤖 Generated with Claude Code

@kaladinlight kaladinlight requested a review from a team as a code owner May 20, 2026 20:59
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 20, 2026

📝 Walkthrough

Walkthrough

This PR adds a new TradeQuoteError.InsufficientFunds, normalizes THORnode/HTTP error messages to identify insufficient-funds and trading-halted cases in getQuote, updates Relay's error mapping to the new enum, and wires the error through validation, UI translation, and user-facing error lists.

Changes

InsufficientFunds Error Type and Integration

Layer / File(s) Summary
Error type contract and swapper mappings
packages/swapper/src/types.ts, packages/swapper/src/thorchain-utils/types.ts, packages/swapper/src/swappers/RelaySwapper/constant.ts
TradeQuoteError adds InsufficientFunds. Exports the THORnode { error: string } type. Relay swapper mapping updated to map RelayErrorCode.InsufficientFunds to TradeQuoteError.InsufficientFunds.
THORchain quote error normalization
packages/swapper/src/thorchain-utils/getQuote.ts
getQuote imports AxiosError and additional Thornode types, normalizes an errorMessage from HTTP failures or 2xx { error } bodies, maps known messages to specific errors (insufficient-fee / trading-halted), then falls back to existing unknown/error handling or returns a success.
State and UI integration
src/state/apis/swapper/helpers/validateTradeQuote.ts, src/components/MultiHopTrade/components/TradeInput/getQuoteErrorTranslation.ts, src/state/slices/tradeQuoteSlice/constants.ts
validateTradeQuote treats SwapperTradeQuoteError.InsufficientFunds as a no-metadata error. UI translation switches now recognize InsufficientFunds. SWAPPER_USER_ERRORS includes the new error.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 I sniffed the bugs and hopped around the code,
Found fees too small where balances owed,
I stitched a type and routed every clue,
Now errors say "InsufficientFunds" true,
Hooray — the swapper knows when wallets are low!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main changes: introducing a new InsufficientFunds error classification for Relay and fixing Thornode HTTP error response handling in the swapper.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 fix/swapper-quote-error-classification

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 and usage tips.

…or responses

- Add TradeQuoteError.InsufficientFunds, route Relay's InsufficientFunds error
  to it, wire it through validateTradeQuote and SWAPPER_USER_ERRORS so users
  see "insufficient funds for trade" and the quote stays in the available list
- Inspect Thornode's non-2xx response body (`{code, message, details}`) in
  getQuote so "trading is halted" surfaces as TradingHalted instead of falling
  through to the generic quote-error translation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@kaladinlight kaladinlight force-pushed the fix/swapper-quote-error-classification branch from 4e8861c to 8225d15 Compare May 20, 2026 21:12
@kaladinlight kaladinlight enabled auto-merge (squash) May 20, 2026 21:14
@kaladinlight kaladinlight merged commit 4331d00 into develop May 20, 2026
4 checks passed
@kaladinlight kaladinlight deleted the fix/swapper-quote-error-classification branch May 20, 2026 21:22
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