Skip to content

Commit 81c5841

Browse files
fix: cp-7.65.0 totals in MUSD conversion using max button (#26029)
## **Description** Cherry-pick #26015 into `7.65.0` release. Applies a Yarn patch to `@metamask/transaction-pay-controller` instead of bumping controller version to avoid unrelated changes. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: #25972 ## **Manual testing steps** ## **Screenshots/Recordings** ## **Pre-merge author checklist** - [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. ## **Pre-merge reviewer checklist** - [ ] 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 quoting/totals and stablecoin detection, which can affect displayed costs and max-amount behavior across networks; mitigated by being a targeted patch and limited app-side changes. > > **Overview** > Fixes transaction pay quote/total calculations by **patching `@metamask/transaction-pay-controller` 12.1.0** rather than bumping the dependency. > > The patch centralizes a multi-chain `STABLECOINS` list, treats stablecoins as $1 in token fiat-rate logic, and changes `targetAmount` across quotes/totals to be a `FiatValue` summed via `sumFiat` (avoiding incorrect max/totals math). Relay quote normalization now accounts for `fees.subsidized` by zeroing provider fees when subsidized and optionally including the subsidized amount in the computed target fiat value; Bridge normalization aligns `targetAmount` to fiat-only as well. > > On the mobile side, `useTokenFiatRates` now uses a stablecoin allowlist (Mainnet/Arbitrum/Linea/Polygon) to return a fixed USD rate of `1`, and the related unit test is generalized accordingly. The Transaction Pay controller messenger drops the unused `TokenListController:getState` action, and `package.json`/`yarn.lock` are updated to consume the patched controller via Yarn’s `patch:` protocol. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 61d257e. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent aec791a commit 81c5841

6 files changed

Lines changed: 556 additions & 32 deletions

File tree

.yarn/patches/@metamask-transaction-pay-controller-npm-12.1.0-226665ee88.patch

Lines changed: 501 additions & 0 deletions
Large diffs are not rendered by default.

app/components/Views/confirmations/hooks/tokens/useTokenFiatRates.test.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ import { CHAIN_IDS } from '@metamask/transaction-controller';
22
import { backgroundState } from '../../../../../util/test/initial-root-state';
33
import { renderHookWithProvider } from '../../../../../util/test/renderWithProvider';
44
import { TokenFiatRateRequest, useTokenFiatRates } from './useTokenFiatRates';
5-
import { ARBITRUM_USDC } from '../../constants/perps';
6-
import { POLYGON_USDCE } from '../../constants/predict';
75

86
jest.mock('../../../../../util/address', () => ({
97
toChecksumAddress: jest.fn((address) => address),
@@ -107,11 +105,11 @@ describe('useTokenFiatRates', () => {
107105
expect(result).toEqual([CONVERSION_RATE_1_MOCK]);
108106
});
109107

110-
it('returns fixed exchange rate if Arbitrum USDC and selected currency is USD', () => {
108+
it('returns fixed exchange rate for stablecoin when currency is USD', () => {
111109
const result = runHook({
112110
requests: [
113111
{
114-
address: ARBITRUM_USDC.address,
112+
address: '0xaf88d065e77c8cc2239327c5edb3a432268e5831',
115113
chainId: CHAIN_IDS.ARBITRUM,
116114
currency: 'usd',
117115
},
@@ -121,20 +119,6 @@ describe('useTokenFiatRates', () => {
121119
expect(result).toEqual([1]);
122120
});
123121

124-
it('returns fixed exchange rate if Polygon USDCE and selected currency is USD', () => {
125-
const result = runHook({
126-
requests: [
127-
{
128-
address: POLYGON_USDCE.address,
129-
chainId: CHAIN_IDS.POLYGON,
130-
currency: 'usd',
131-
},
132-
],
133-
});
134-
135-
expect(result).toEqual([1]);
136-
});
137-
138122
it('returns USD conversion rates if currency is USD', () => {
139123
const result = runHook({
140124
requests: [

app/components/Views/confirmations/hooks/tokens/useTokenFiatRates.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,26 @@ import { useMemo } from 'react';
1010
import { useDeepMemo } from '../useDeepMemo';
1111
import { toChecksumAddress } from '../../../../../util/address';
1212
import { CHAIN_IDS } from '@metamask/transaction-controller';
13-
import { ARBITRUM_USDC } from '../../constants/perps';
14-
import { POLYGON_USDCE } from '../../constants/predict';
13+
14+
// Pending conversion to a remote feature flag
15+
const STABLECOINS: Record<Hex, Hex[]> = {
16+
[CHAIN_IDS.MAINNET]: [
17+
'0xaca92e438df0b2401ff60da7e4337b687a2435da', // MUSD
18+
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', // USDC
19+
'0xdac17f958d2ee523a2206206994597c13d831ec7', // USDT
20+
],
21+
[CHAIN_IDS.ARBITRUM]: [
22+
'0xaf88d065e77c8cc2239327c5edb3a432268e5831', // USDC
23+
],
24+
[CHAIN_IDS.LINEA_MAINNET]: [
25+
'0xaca92e438df0b2401ff60da7e4337b687a2435da', // MUSD
26+
'0x176211869ca2b568f2a7d4ee941e073a821ee1ff', // USDC
27+
'0xa219439258ca9da29e9cc4ce5596924745e12b93', // USDT
28+
],
29+
[CHAIN_IDS.POLYGON]: [
30+
'0x2791bca1f2de4661ed88a30c99a7a9449aa84174', // USDC.e
31+
],
32+
};
1533

1634
export interface TokenFiatRateRequest {
1735
address: Hex;
@@ -32,15 +50,11 @@ export function useTokenFiatRates(requests: TokenFiatRateRequest[]) {
3250
const currency = currencyOverride ?? selectedCurrency;
3351
const isUsd = currency.toLowerCase() === 'usd';
3452

35-
const isArbitrumUSDC =
36-
address.toLowerCase() === ARBITRUM_USDC.address.toLowerCase() &&
37-
chainId === CHAIN_IDS.ARBITRUM;
38-
39-
const isPolygonUSDCE =
40-
address.toLowerCase() === POLYGON_USDCE.address.toLowerCase() &&
41-
chainId === CHAIN_IDS.POLYGON;
53+
const isStablecoin = STABLECOINS[chainId]?.includes(
54+
address.toLowerCase() as Hex,
55+
);
4256

43-
if (isUsd && (isArbitrumUSDC || isPolygonUSDCE)) {
57+
if (isUsd && isStablecoin) {
4458
return 1;
4559
}
4660

app/core/Engine/messengers/transaction-pay-controller-messenger/transaction-pay-controller-messenger.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ export function getTransactionPayControllerMessenger(
3232
'NetworkController:getNetworkClientById',
3333
'RemoteFeatureFlagController:getState',
3434
'TokenBalancesController:getState',
35-
'TokenListController:getState',
3635
'TokenRatesController:getState',
3736
'TokensController:getState',
3837
'TransactionController:estimateGas',

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@
299299
"@metamask/swappable-obj-proxy": "^2.1.0",
300300
"@metamask/swaps-controller": "^15.0.0",
301301
"@metamask/transaction-controller": "^62.14.0",
302-
"@metamask/transaction-pay-controller": "^12.1.0",
302+
"@metamask/transaction-pay-controller": "patch:@metamask/transaction-pay-controller@npm%3A12.1.0#~/.yarn/patches/@metamask-transaction-pay-controller-npm-12.1.0-226665ee88.patch",
303303
"@metamask/tron-wallet-snap": "^1.19.2",
304304
"@metamask/utils": "^11.8.1",
305305
"@ngraveio/bc-ur": "^1.1.6",

yarn.lock

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9829,7 +9829,7 @@ __metadata:
98299829
languageName: node
98309830
linkType: hard
98319831

9832-
"@metamask/transaction-pay-controller@npm:^12.1.0":
9832+
"@metamask/transaction-pay-controller@npm:12.1.0":
98339833
version: 12.1.0
98349834
resolution: "@metamask/transaction-pay-controller@npm:12.1.0"
98359835
dependencies:
@@ -9855,6 +9855,32 @@ __metadata:
98559855
languageName: node
98569856
linkType: hard
98579857

9858+
"@metamask/transaction-pay-controller@patch:@metamask/transaction-pay-controller@npm%3A12.1.0#~/.yarn/patches/@metamask-transaction-pay-controller-npm-12.1.0-226665ee88.patch":
9859+
version: 12.1.0
9860+
resolution: "@metamask/transaction-pay-controller@patch:@metamask/transaction-pay-controller@npm%3A12.1.0#~/.yarn/patches/@metamask-transaction-pay-controller-npm-12.1.0-226665ee88.patch::version=12.1.0&hash=a5ca90"
9861+
dependencies:
9862+
"@ethersproject/abi": "npm:^5.7.0"
9863+
"@ethersproject/contracts": "npm:^5.7.0"
9864+
"@metamask/assets-controllers": "npm:^99.2.0"
9865+
"@metamask/base-controller": "npm:^9.0.0"
9866+
"@metamask/bridge-controller": "npm:^65.2.0"
9867+
"@metamask/bridge-status-controller": "npm:^65.0.1"
9868+
"@metamask/controller-utils": "npm:^11.18.0"
9869+
"@metamask/gas-fee-controller": "npm:^26.0.2"
9870+
"@metamask/messenger": "npm:^0.3.0"
9871+
"@metamask/metamask-eth-abis": "npm:^3.1.1"
9872+
"@metamask/network-controller": "npm:^29.0.0"
9873+
"@metamask/remote-feature-flag-controller": "npm:^4.0.0"
9874+
"@metamask/transaction-controller": "npm:^62.14.0"
9875+
"@metamask/utils": "npm:^11.9.0"
9876+
bignumber.js: "npm:^9.1.2"
9877+
bn.js: "npm:^5.2.1"
9878+
immer: "npm:^9.0.6"
9879+
lodash: "npm:^4.17.21"
9880+
checksum: 10/8503ba5e75a7aa5d49f95160b24f4ba2c9df2395a329b2747f8e29a1375df432c202cc57c29933f099db8f7524d011084f9f9190a55035eca3a12af363eec8aa
9881+
languageName: node
9882+
linkType: hard
9883+
98589884
"@metamask/tron-wallet-snap@npm:^1.19.2":
98599885
version: 1.19.2
98609886
resolution: "@metamask/tron-wallet-snap@npm:1.19.2"
@@ -34893,7 +34919,7 @@ __metadata:
3489334919
"@metamask/test-dapp-multichain": "npm:^0.17.1"
3489434920
"@metamask/test-dapp-solana": "npm:^0.3.0"
3489534921
"@metamask/transaction-controller": "npm:^62.14.0"
34896-
"@metamask/transaction-pay-controller": "npm:^12.1.0"
34922+
"@metamask/transaction-pay-controller": "patch:@metamask/transaction-pay-controller@npm%3A12.1.0#~/.yarn/patches/@metamask-transaction-pay-controller-npm-12.1.0-226665ee88.patch"
3489734923
"@metamask/tron-wallet-snap": "npm:^1.19.2"
3489834924
"@metamask/utils": "npm:^11.8.1"
3489934925
"@ngraveio/bc-ur": "npm:^1.1.6"

0 commit comments

Comments
 (0)