Skip to content

Commit 1a802e0

Browse files
authored
fix: Fix batch transaction_type in metrics for pay transactions (#8469)
## Explanation <!-- Thanks for your contribution! Take a moment to answer these questions so that reviewers have the information they need to properly understand your changes: * What is the current state of things and why does it need to change? * What is the solution your changes offer and how does it work? * Are there any changes whose purpose might not obvious to those unfamiliar with the domain? * If your primary goal was to update one package but you found you had to update another one along the way, why did you do so? * If you had to upgrade a dependency, why did you do so? --> Resolve the effective transaction type from `nestedTransactions` when the parent is a batch transaction, so relay deposits for mUSD conversions (and other supported types) are correctly classified even when batched. Result of transaction metrics in mobile with preview build: <img width="675" height="868" alt="Screenshot 2026-04-15 at 15 22 01" src="https://github.com/user-attachments/assets/ee76d27b-f8c9-464d-89d6-1ce0e8d6e215" /> ## References <!-- Are there any issues that this pull request is tied to? Are there other links that reviewers should consult to understand these changes better? Are there client or consumer pull requests to adopt any breaking changes? For example: * Fixes #12345 * Related to #67890 --> * Fixes https://consensyssoftware.atlassian.net/browse/CONF-1190 ## Checklist - [X] I've updated the test suite for new or updated code as appropriate - [X] 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) - [X] 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] > **Medium Risk** > Changes how relay deposit transactions are typed when the parent transaction is `batch`, which can affect metrics and downstream type-based handling. Adds a new `TransactionType` enum value that consumers may need to recognize. > > **Overview** > Fixes MetaMask Pay relay submissions so relay deposit transactions are **typed based on the underlying nested transaction** when the parent is `TransactionType.batch`, rather than always using the top-level `batch` type. > > Adds a new `TransactionType.musdRelayDeposit` and maps `musdConversion -> musdRelayDeposit` in `RELAY_DEPOSIT_TYPES`, with expanded unit tests covering batch/nested resolution and fallback behavior. Changelogs are updated for both `transaction-controller` and `transaction-pay-controller`. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit dcb47ad. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent f105195 commit 1a802e0

6 files changed

Lines changed: 94 additions & 2 deletions

File tree

packages/transaction-controller/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Add `MantleLayer1GasFeeFlow` with `tokenRatio` conversion for accurate MNT-denominated gas estimates for Mantle and MantleSepolia ([#8386](https://github.com/MetaMask/core/pull/8386))
13+
- Add `musdRelayDeposit` to `TransactionType` enum ([#8469](https://github.com/MetaMask/core/pull/8469))
1314

1415
### Changed
1516

packages/transaction-controller/src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,11 @@ export enum TransactionType {
801801
*/
802802
musdConversion = 'musdConversion',
803803

804+
/**
805+
* Deposit funds for a Relay quote when the parent transaction is an mUSD conversion.
806+
*/
807+
musdRelayDeposit = 'musdRelayDeposit',
808+
804809
/**
805810
* Deposit funds for Across quote via Perps.
806811
*/

packages/transaction-pay-controller/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Resolve the effective transaction type from `nestedTransactions` when the parent is a batch transaction ([#8469](https://github.com/MetaMask/core/pull/8469))
13+
1014
## [19.1.2]
1115

1216
### Changed

packages/transaction-pay-controller/src/strategy/relay/constants.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const RELAY_PENDING_STATUSES: RelayStatus[] = [
2626
];
2727

2828
export const RELAY_DEPOSIT_TYPES: Record<string, TransactionType> = {
29+
[TransactionType.musdConversion]: TransactionType.musdRelayDeposit,
2930
[TransactionType.predictDeposit]: TransactionType.predictRelayDeposit,
3031
[TransactionType.perpsDeposit]: TransactionType.perpsRelayDeposit,
3132
};

packages/transaction-pay-controller/src/strategy/relay/relay-submit.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,66 @@ describe('Relay Submit Utils', () => {
270270
);
271271
});
272272

273+
it('uses musdRelayDeposit type when parent transaction is musdConversion', async () => {
274+
request.transaction = {
275+
...request.transaction,
276+
type: TransactionType.musdConversion,
277+
} as TransactionMeta;
278+
279+
await submitRelayQuotes(request);
280+
281+
expect(addTransactionMock).toHaveBeenCalledTimes(1);
282+
expect(addTransactionMock).toHaveBeenCalledWith(
283+
expect.anything(),
284+
expect.objectContaining({
285+
type: TransactionType.musdRelayDeposit,
286+
}),
287+
);
288+
});
289+
290+
it.each([
291+
[TransactionType.predictDeposit, TransactionType.predictRelayDeposit],
292+
[TransactionType.perpsDeposit, TransactionType.perpsRelayDeposit],
293+
[TransactionType.musdConversion, TransactionType.musdRelayDeposit],
294+
])(
295+
'resolves %s from nestedTransactions when type is batch',
296+
async (nestedType, expectedType) => {
297+
request.transaction = {
298+
...request.transaction,
299+
type: TransactionType.batch,
300+
nestedTransactions: [{ type: nestedType }],
301+
} as TransactionMeta;
302+
303+
await submitRelayQuotes(request);
304+
305+
expect(addTransactionMock).toHaveBeenCalledTimes(1);
306+
expect(addTransactionMock).toHaveBeenCalledWith(
307+
expect.anything(),
308+
expect.objectContaining({
309+
type: expectedType,
310+
}),
311+
);
312+
},
313+
);
314+
315+
it('falls back to relayDeposit when type is batch and nestedTransactions have no mapped type', async () => {
316+
request.transaction = {
317+
...request.transaction,
318+
type: TransactionType.batch,
319+
nestedTransactions: [{ type: TransactionType.tokenMethodApprove }],
320+
} as TransactionMeta;
321+
322+
await submitRelayQuotes(request);
323+
324+
expect(addTransactionMock).toHaveBeenCalledTimes(1);
325+
expect(addTransactionMock).toHaveBeenCalledWith(
326+
expect.anything(),
327+
expect.objectContaining({
328+
type: TransactionType.relayDeposit,
329+
}),
330+
);
331+
});
332+
273333
it('adds transaction with gas fee token if isSourceGasFeeToken', async () => {
274334
request.quotes[0].fees.isSourceGasFeeToken = true;
275335

packages/transaction-pay-controller/src/strategy/relay/relay-submit.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ async function submitViaTransactionController(
551551
networkClientId,
552552
origin: ORIGIN_METAMASK,
553553
requireApproval: false,
554-
type: getRelayDepositType(transaction.type),
554+
type: getRelayDepositType(getEffectiveTransactionType(transaction)),
555555
},
556556
);
557557
} else {
@@ -576,7 +576,7 @@ async function submitViaTransactionController(
576576
type: getTransactionType(
577577
isPostQuote,
578578
index,
579-
transaction.type,
579+
getEffectiveTransactionType(transaction),
580580
normalizedParams.length,
581581
),
582582
};
@@ -664,3 +664,24 @@ function getRelayDepositType(
664664
TransactionType.relayDeposit
665665
);
666666
}
667+
668+
/**
669+
* Get the effective transaction type, resolving through nested transactions
670+
* when the top-level type is `batch`.
671+
*
672+
* @param transaction - The transaction metadata.
673+
* @returns The resolved type from nested transactions, or the top-level type.
674+
*/
675+
function getEffectiveTransactionType(
676+
transaction: TransactionMeta,
677+
): TransactionMeta['type'] {
678+
if (transaction.type !== TransactionType.batch) {
679+
return transaction.type;
680+
}
681+
682+
const nestedType = transaction.nestedTransactions?.find(
683+
(tx) => tx.type && RELAY_DEPOSIT_TYPES[tx.type] !== undefined,
684+
)?.type;
685+
686+
return nestedType ?? transaction.type;
687+
}

0 commit comments

Comments
 (0)