feat(transaction-pay-controller): surface fiat ramps quote error as fiatPayment.quoteError#9030
feat(transaction-pay-controller): surface fiat ramps quote error as fiatPayment.quoteError#9030amitabh94 wants to merge 2 commits into
Conversation
…iatPayment.quoteError Add `TransactionFiatQuoteError` type and `quoteError` field to `TransactionFiatPayment` so the mobile UI can display provider-specific rejection messages (e.g. "Minimum purchase is $X") for providers without client-side structured limits. The fiat quote flow classifies the first error entry from `quotes.error` as `LIMIT_EXCEEDED` when the message matches limit keywords, or `QUOTE_FAILED` otherwise; the field is cleared on success. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
@metamaskbot publish-preview |
| fiatPayment.quoteError = quoteError; | ||
| }, | ||
| transactionId, | ||
| }); |
There was a problem hiding this comment.
Superseded fetch persists quoteError
High Severity
The getFiatQuotes catch handler always calls updateFiatPayment to set quoteError but never checks request.signal. A superseded in-flight attempt can still write a stale provider error into fiatPayment after a newer refresh already succeeded, so the limit UI can show a rejection while current quotes are valid. The handler also does not clear rampsQuote, so error and quote fields can disagree.
Reviewed by Cursor Bugbot for commit a3d867d. Configure here.
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |
…d867de5 (MetaMask/core#9030) Adds fiatPayment.quoteError for surfacing backend provider limit messages. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…uote fetch The fiat strategy was calling RampsController:getQuotes with restrictToKnownOrNativeProviders: true, which silently drops aggregator providers (type = 'aggregator', e.g. onramp.money) and returns an empty quote list when no native provider (e.g. Transak) is available in the user's region. This makes quotes impossible in regions served only by aggregators — India with onramp.money + ETH is a concrete example: the eligibility gate (getBestProviderForAsset) correctly returns onramp.money, but the subsequent quote call refused to use it, causing an infinite spinner. The restriction was originally added for headless UB2 to enforce Transak- native-only quotes. The fiat strategy (moneyAccountDeposit path) does not have that constraint — the gate already verified that a supporting provider exists, so the quote call should trust it and use whatever provider the cascade selects. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
@metamask-bot publish preview |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 86a299a. Configure here.
| fiatPayment.quoteError = quoteError; | ||
| }, | ||
| transactionId, | ||
| }); |
There was a problem hiding this comment.
quoteError set for non-ramps failures
Medium Severity
The shared catch in getFiatQuotes always writes fiatPayment.quoteError, including when getRampsQuote never ran (relay errors, invalid amounts, unsupported multi-token). Those cases get { code: 'QUOTE_FAILED' } with no provider message, which misrepresents a ramps rejection and can drive limit/quote UI from stale or irrelevant state.
Reviewed by Cursor Bugbot for commit 86a299a. Configure here.
|
@metamask-bot publish preview |
|
@metamaskbot publish-preview |
|
Preview builds have been published. Learn how to use preview builds in other projects. Expand for full list of packages and versions. |


Explanation
Stacked on #8987. The fiat strategy currently swallows the ramps quote error (
getFiatQuotescatch→return []), so the client can only show a generic "no quotes" message. This surfaces the provider's specific rejection (e.g. "Minimum purchase is $X") so MetaMask Pay can display it for providers without client-side structured limits.Changes
TransactionFiatPayment.quoteError?: { code: 'LIMIT_EXCEEDED' | 'QUOTE_FAILED'; message?: string }(newTransactionFiatQuoteErrortype, exported).getRampsQuoteclassifies the firstquotes.errorentry (LIMIT_EXCEEDEDwhen the message matches limit keywords and not rate/request, elseQUOTE_FAILED) and attaches it to the thrown error.getFiatQuoteswritesfiatPayment.quoteErroron failure (via the existingupdateFiatPaymentmechanism, same asrampsQuote) and clears it on success. Still returns[]on no-quote.Additive; provider scoping and
rampsQuotepopulation unchanged. Consumer: mobileuseFiatBuyLimitAlertpassesquoteError.messageasbackendErrorinto the sharedgetProviderLimitMessage(UB2 parity).Note
jest.config.jsmoduleNameMapperaddition is a local subpath-resolution workaround to runfiat-quotes.test.ts; drop before merge if CI resolves it without.Checklist
🤖 Generated with Claude Code
Note
Medium Risk
Additive API is low risk, but turning off
restrictToKnownOrNativeProviderschanges which on-ramp providers can be selected for fiat deposits.Overview
Fiat ramps quote failures now persist structured errors on
TransactionFiatPaymentinstead of only returning an empty quote list, so clients (e.g. mobile Pay) can show provider-specific copy like minimum purchase amounts.Adds optional
quoteError(LIMIT_EXCEEDED|QUOTE_FAILED, optionalmessage) and exportsTransactionFiatQuoteError. On ramps failure,getRampsQuotereads the firstquotes.errorentry, classifies the message (limit keywords vs rate/request exclusions), andgetFiatQuoteswrites that viaupdateFiatPaymentin the existingcatchpath; success clearsquoteError. Non-ramps failures still getQUOTE_FAILEDwithout a message.RampsController:getQuotesfor the fiat strategy now passesrestrictToKnownOrNativeProviders: falseso aggregator providers can servemoneyAccountDepositwhere native-only ramps are unavailable.Includes
fiat-quotestests for error classification/clearing and a JestmoduleNameMappertweak for eth keyring v2 subpaths (noted as optional for CI).Reviewed by Cursor Bugbot for commit 86a299a. Bugbot is set up for automated code reviews on this repo. Configure here.