chore(runway): cherry-pick feat: block MetaMask Pay submissions without quotes and handle no-op quotes#33371
chore(runway): cherry-pick feat: block MetaMask Pay submissions without quotes and handle no-op quotes#33371runway-github[bot] wants to merge 1 commit into
Conversation
…quotes cp-8.3.0 (#33194) Mobile side of MetaMask/core#9484, which makes "no conversion needed" an explicit no-op quote and requires quotes at publish time for MetaMask Pay transactions. - Bump `@metamask/transaction-pay-controller` to `^25.0.0` (includes the no-op quote change) and `@metamask/transaction-controller` to `69.0.0` (required by the new pay controller). - `validateRequiredQuote` now also requires quotes for post-quote withdraw types when the post-quote flag is enabled; direct routes are allowed only when the controller state confirms them. - `validateRequiredQuote` also covers pay deposit and conversion types (perps deposits, predict deposits, mUSD conversion): they may submit without a quote only when the user pays with the required token itself and no conversion is pending, or the deposit is funded by a fiat on-ramp order. - New blocking legs in `useNoPayTokenQuotesAlert`: withdraw flows where the pay config or destination token is not set on the controller yet, and pay deposit/conversion flows where neither a payment token nor a fiat payment method is set. - No-op quotes (strategy `none`) are filtered everywhere: fee, duration, and step UI, metrics, and the publish guard. A no-op quote never counts as an executable quote; direct routes are validated from controller state instead, keeping the publish guard consistent with the confirmation alerts. - Metrics: add `mm_pay_quote_skipped`; strategy and step totals count only executable quotes. CHANGELOG entry: Improved quote validation for MetaMask Pay deposits, conversions and withdrawals Refs: MetaMask/core#9484 ```gherkin Feature: MetaMask Pay quote validation Scenario: user withdraws to a different destination token Given the user has a Predict, Perps, or Money account balance When the user enters an amount and a quote is available Then the confirmation completes with the selected destination token Scenario: user withdraws to the same token and chain Given the user selects the source token as the destination Then the withdrawal completes as a direct transfer Scenario: user deposits or converts paying with another token Given the user selects a payment token on a different chain When a quote is available Then the transaction completes with the conversion Scenario: user deposits or converts paying with the required token Given the user selects the required token itself as the payment token Then the transaction completes as a direct transfer Scenario: user deposits paying with fiat Given the user selects a fiat payment method Then the confirmation is not blocked by the payment token alert ``` N/A N/A N/A - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. - [ ] I've tested on Android - Ideally on a mid-range device; emulator is acceptable - [ ] I've tested with a power user scenario - Use these [power-user SRPs](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/edit-v2/401401446401?draftShareId=9d77e1e1-4bdc-4be1-9ebb-ccd916988d93) to import wallets with many accounts and tokens - [ ] I've instrumented key operations with Sentry traces for production performance metrics - See [`trace()`](/app/util/trace.ts) for usage and [`addToken`](/app/components/Views/AddAsset/components/AddCustomToken/AddCustomToken.tsx#L274) for an example For performance guidelines and tooling, see the [Performance Guide](https://consensyssoftware.atlassian.net/wiki/spaces/TL1/pages/400085549067/Performance+Guide+for+Engineers). - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Changes transaction publish and confirmation blocking for MetaMask Pay funding paths; incorrect direct-route exceptions could still allow unfunded submissions or block legitimate flows. > > **Overview** > Bumps **`@metamask/transaction-pay-controller`** to **^25.0.0** (no-op quotes for direct routes) and aligns mobile with stricter publish-time and confirmation-time Pay guards. > > **No-op quotes** (`strategy: none`) are treated as non-executable everywhere: the quote selector filters them for UI, **`validateRequiredQuote`** and metrics only count executable quotes, and **`mm_pay_quote_skipped`** is set when no-op quotes were present. > > **Publish** (`validateRequiredQuote`) now also applies to **pay-token-required** deposits/conversions (perps/predict/mUSD, etc.) and **post-quote withdraws** when the feature flag is on. Submission without an executable quote is allowed only for validated direct routes (required token, no pending conversion), fiat orders with **`orderId`**, or post-quote withdraws with **`isPostQuote`** and no pending **`sourceAmounts`**—including withdraws with no destination token selected. > > **Confirmation** adds blocking **`NoPayTokenQuotes`** cases: withdraws with token selection enabled before Pay config is initialised (`!isPostQuote`), and pay-token-required types with no payment token and no fiat method—mirroring publish rules so users cannot confirm timing races that used to submit unfunded txs. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit cd7b38f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
|
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
🔍 Smart E2E Test Selection⏭️ Smart E2E selection skipped - PR targets a release or stable branch (release/* or stable) All E2E tests pre-selected. |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
|
Warning MetaMask internal reviewing guidelines:
|
Description
Mobile side of MetaMask/core#9484, which makes "no conversion needed" an
explicit no-op quote and requires quotes at publish time for MetaMask
Pay transactions.
@metamask/transaction-pay-controllerto^25.0.0(includes theno-op quote change) and
@metamask/transaction-controllerto69.0.0(required by the new pay controller).
validateRequiredQuotenow also requires quotes for post-quotewithdraw types when the post-quote flag is enabled; direct routes are
allowed only when the controller state confirms them.
validateRequiredQuotealso covers pay deposit and conversion types(perps deposits, predict deposits, mUSD conversion): they may submit
without a quote only when the user pays with the required token itself
and no conversion is pending, or the deposit is funded by a fiat on-ramp
order.
useNoPayTokenQuotesAlert: withdraw flows wherethe pay config or destination token is not set on the controller yet,
and pay deposit/conversion flows where neither a payment token nor a
fiat payment method is set.
none) are filtered everywhere: fee, duration,and step UI, metrics, and the publish guard. A no-op quote never counts
as an executable quote; direct routes are validated from controller
state instead, keeping the publish guard consistent with the
confirmation alerts.
mm_pay_quote_skipped; strategy and step totals countonly executable quotes.
Changelog
CHANGELOG entry: Improved quote validation for MetaMask Pay deposits,
conversions and withdrawals
Related issues
Refs: MetaMask/core#9484
Manual testing steps
Screenshots/Recordings
N/A
Before
N/A
After
N/A
Pre-merge author checklist
Docs and MetaMask Mobile
Coding
Standards.
if applicable
guidelines).
Not required for external contributors.
Performance checks (if applicable)
SRPs
to import wallets with many accounts and tokens
performance metrics
trace()for usage andaddTokenfor an example
For performance guidelines and tooling, see the Performance
Guide.
Pre-merge reviewer checklist
app, test code being changed).
in the ticket it closes and includes the necessary testing evidence such
as recordings and or screenshots.
Note
High Risk
Changes transaction publish and confirmation blocking for MetaMask Pay
funding paths; incorrect direct-route exceptions could still allow
unfunded submissions or block legitimate flows.
Overview
Bumps
@metamask/transaction-pay-controllerto ^25.0.0 (no-opquotes for direct routes) and aligns mobile with stricter publish-time
and confirmation-time Pay guards.
No-op quotes (
strategy: none) are treated as non-executableeverywhere: the quote selector filters them for UI,
validateRequiredQuoteand metrics only count executable quotes,and
mm_pay_quote_skippedis set when no-op quotes were present.Publish (
validateRequiredQuote) now also applies topay-token-required deposits/conversions (perps/predict/mUSD, etc.)
and post-quote withdraws when the feature flag is on. Submission
without an executable quote is allowed only for validated direct routes
(required token, no pending conversion), fiat orders with
orderId,or post-quote withdraws with
isPostQuoteand no pendingsourceAmounts—including withdraws with no destination tokenselected.
Confirmation adds blocking
NoPayTokenQuotescases: withdrawswith token selection enabled before Pay config is initialised
(
!isPostQuote), and pay-token-required types with no payment token andno fiat method—mirroring publish rules so users cannot confirm timing
races that used to submit unfunded txs.
Reviewed by Cursor Bugbot for commit
cd7b38f. Bugbot is set up for automated
code reviews on this repo. Configure
here.