fix: Add resolveSourceAmount callback - #9817
Merged
Merged
Conversation
resolveSourceAmount callback
10 tasks
OGPoyraz
marked this pull request as ready for review
August 11, 2026 08:03
jpuri
reviewed
Aug 11, 2026
|
|
||
| /** Required (target) token to be covered. */ | ||
| token: TransactionPayRequiredToken; | ||
| }; |
Contributor
There was a problem hiding this comment.
If we just pass may be transaction object and transactionMeta here ?
Member
Author
There was a problem hiding this comment.
Agreed it's relevant for callbacks like getDelegationTransaction but for specific to MA override, isMax and paymentOverride is in fact enough for now. (I will remove paymentToken and token thanks for the ping)
Shall we add that in future if we need transaction?
Contributor
There was a problem hiding this comment.
ok, lets keep it as future task
Member
Author
There was a problem hiding this comment.
jpuri
previously approved these changes
Aug 11, 2026
jpuri
approved these changes
Aug 11, 2026
pull Bot
pushed a commit
to dmrazzy/core
that referenced
this pull request
Aug 11, 2026
## Explanation Release `1186.0.0` with a minor version bump for: - **`@metamask/transaction-pay-controller`** `26.2.3` → `26.3.0` ### `@metamask/transaction-pay-controller@26.3.0` #### Added - Add optional `resolveSourceAmount` constructor option to `TransactionPayController`, allowing clients to supply an exact atomic source amount for a required token that bypasses the default fiat-derived source calculation ([MetaMask#9817](MetaMask#9817)) #### Changed - Bump `@metamask/transaction-controller` from `^69.5.0` to `^69.5.1` ([MetaMask#9798](MetaMask#9798)) - Bump `@metamask/keyring-controller` from `^27.1.0` to `^27.1.1` ([MetaMask#9791](MetaMask#9791)) - Bump `@metamask/assets-controllers` from `^111.0.0` to `^111.1.0` ([MetaMask#9793](MetaMask#9793)) - Bump `@metamask/assets-controller` from `^13.1.1` to `^13.1.2` ([MetaMask#9813](MetaMask#9813)) ### Dependency updates No downstream packages depend on `@metamask/transaction-pay-controller`, so no additional changelog entries were needed. ## References - [MetaMask#9817](MetaMask#9817) — Add `resolveSourceAmount` constructor option - [MetaMask#9798](MetaMask#9798) — Bump transaction-controller - [MetaMask#9791](MetaMask#9791) — Bump keyring-controller - [MetaMask#9793](MetaMask#9793) — Bump assets-controllers - [MetaMask#9813](MetaMask#9813) — Bump assets-controller ## Checklist - [ ] I've updated the test suite for new or updated code as appropriate - [ ] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Low Risk** > Version and changelog-only release PR with no code changes in the diff. > > **Overview** > **Release `1186.0.0`** updates the monorepo version and publishes **`@metamask/transaction-pay-controller` `26.2.3` → `26.3.0`**. > > The new **`26.3.0`** changelog section documents what ships in that package: an optional **`resolveSourceAmount`** constructor on `TransactionPayController` so clients can supply an exact atomic source amount and skip the default fiat-derived calculation, plus patch bumps to `transaction-controller`, `keyring-controller`, `assets-controllers`, and `assets-controller`. The diff itself is version and changelog bookkeeping only—no application source changes in this PR. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 633bddf. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
pull Bot
pushed a commit
to Reality2byte/metamask-mobile
that referenced
this pull request
Aug 12, 2026
…#34590) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
runway-github Bot
added a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
10 tasks
tommasini
pushed a commit
to MetaMask/metamask-mobile
that referenced
this pull request
Aug 12, 2026
…to `TPC` (#34688) - fix: cp-8.7.0 Add `resolveSourceAmount` callback into `TPC` (#34590) <!-- mms-check directive vocabulary — read by .github/scripts/shared/pr-template-checks.ts at module load to build the validation plan. Directives are invisible in rendered markdown and must NOT be removed or edited without updating the validator registry. type=text Section must contain non-placeholder prose. type=changelog Section must have a valid CHANGELOG entry: line. type=issue-link Section must have a Fixes:/Closes:/Refs: line with a value. type=manual-testing Section must have real testing steps or an explicit N/A. type=screenshot Section must have evidence (image/URL) or an explicit N/A. type=checklist Section must have all checkboxes consciously checked. required=true|false Whether a missing/invalid section runs the validator at all. blocking=true|false Whether a failure of this check fails the CI workflow. Default: false — failures are shown as warnings in the sticky comment but do not block the PR. Sections without a directive are checked for structural presence only. --> ## **Description** <!-- mms-check: type=text required=true --> For a Money Account Max deposit (e.g. "Send from Money Account → Perps"), the pay controller derives the Relay quote's source amount from a fiat conversion (`amountUsd / usdRate`). Since mUSD's rate is just under `$1`, this inflates the mUSD source above the on-chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). This wires up the new generic `resolveSourceAmount` callback added in `@metamask/transaction-pay-controller` (MetaMask/core#9817) so the client supplies the exact atomic redeemable instead: - Adds a `redeemableRaw` field to the `moneyBalance` slice (+ setter/selector). - `useMoneyAccountBalance` stashes the exact atomic redeemable (`vmusdValueInMusd`) so it can be read synchronously outside React. - New `resolveSourceAmount` callback returns that cached atomic amount for Money Account Max (and `undefined` otherwise), registered in the controller init. ## **Changelog** <!-- mms-check: type=changelog required=true blocking=true --> CHANGELOG entry: Fixed max Perps deposits funded from the Money Account sometimes failing at quote time. ## **Related issues** <!-- mms-check: type=issue-link required=true --> Fixes: CONF-1787 Refs: MetaMask/core#9817 ## **Manual testing steps** <!-- mms-check: type=manual-testing required=true --> ```gherkin Feature: Max Perps deposit funded from the Money Account Scenario: user deposits their full Money Account balance into Perps Given a Money Account with a non-trivial balance (e.g. > $30) When the user sends from Money Account to Perps and selects Max Then the Relay quote simulation succeeds (no revert) And the source amount equals the on-chain redeemable, not the grossed-up fiat amount ``` ## **Screenshots/Recordings** <!-- mms-check: type=screenshot required=true --> ### **Before** <!-- Relay simulation reverts on max Perps deposit from Money Account. --> N/A ### **After** <!-- [screenshots/recordings] --> N/A ## **Pre-merge author checklist** <!-- mms-check: type=checklist required=true --> - [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. #### Performance checks (if applicable) - [ ] 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). ## **Pre-merge reviewer checklist** <!-- Reviewer checklist items follow the same semantics as the author checklist: an unchecked box is ambiguous, a checked box means the reviewer consciously assessed that responsibility. See `docs/readme/ready-for-review.md`. --> - [ ] 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] > **Medium Risk** > Touches transaction-pay source-amount resolution for Money Account funding, so a bad cache or address mismatch could under/over-quote max deposits. Scope is narrow and guarded by account matching plus unit tests. > > **Overview** > Fixes intermittent Relay quote failures on **max Money Account → Perps** deposits by supplying the exact on-chain redeemable instead of a fiat-converted amount that could exceed balance. > > Caches atomic redeemable (`vmusdValueInMusd`) in the `moneyBalance` slice from `useMoneyAccountBalance`, then wires a new `resolveSourceAmount` callback into `TransactionPayController` (via `@metamask/transaction-pay-controller` `^26.3.0`) that returns that cached raw amount only for Money Account max flows when the address matches. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 845084f. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> [6f6cb05](6f6cb05) Co-authored-by: Ömer Göktuğ Poyraz <omergoktugpoyraz@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
For a Money Account Max deposit (e.g. "Send from Money Account → Perps"),
calculateSourceAmountderives the Relay quote's sourceamountastoken.amountUsd / usdRate * 10^decimals. Since mUSD'susdRateis just under$1, this inflates the mUSD source above the on‑chain redeemable, so the Relay simulation reverts (the error scales with amount, hence the intermittent failures). The exact redeemable (bare mUSD + vaulted vmUSD) is only known to the client.This adds an optional, generic
resolveSourceAmountconstructor callback:(request) => { sourceAmountRaw } | undefined. It's consulted incalculateSourceAmountafter the existing skip guards and before the fiat gross‑up; a returned raw value is used verbatim (human derived from it), andundefinedfalls through unchanged. Opt‑in per return value, so existing flows are unaffected and no new state fields are added. Also exports the related types.References
Checklist
Note
Medium Risk
Changes how quote source amounts are computed on an opt-in path in transaction-pay quoting; incorrect callback values could cause failed simulations or wrong pay amounts, though default flows are unchanged.
Overview
Adds an optional
resolveSourceAmountconstructor hook onTransactionPayControllerso clients can supply an exact atomic source amount for Relay quotes instead of the default fiat-derived calculation (amountUsd / usdRate).The callback is synchronous, receives
{ isMaxAmount, paymentOverride }, and returns{ sourceAmountRaw }orundefinedto keep existing behavior.TransactionPayControllerforwards it intoupdateSourceAmounts/calculateSourceAmount, which consult it after skip guards (same-token, zero amount) and before fiat math and max-balance logic; a returned raw value is used verbatim with human amount derived from payment token decimals.Related types are exported from the package public API.
calculateSourceAmountalso moves the zero-amount check earlier soresolveSourceAmountis not called for skipped tokens. Tests cover forwarding from the controller, verbatim use, fallback, and guard behavior; changelog documents the new option.Reviewed by Cursor Bugbot for commit 9833a9e. Bugbot is set up for automated code reviews on this repo. Configure here.