Skip to content
4 changes: 4 additions & 0 deletions packages/bridge-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Quotes as returned by `fetchQuotes` now include a `gasSponsored` property ([#6687](https://github.com/MetaMask/core/pull/6687))

### Changed

- Bump `@metamask/network-controller` from `^24.2.2` to `^24.3.0` ([#6883](https://github.com/MetaMask/core/pull/6883))
Expand Down
43 changes: 43 additions & 0 deletions packages/bridge-controller/src/bridge-controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {
StatusTypes,
type BridgeControllerMessenger,
type QuoteResponse,
type GenericQuoteRequest,
} from './types';
import * as balanceUtils from './utils/balance';
import { getNativeAssetForChainId, isSolanaChainId } from './utils/bridge';
Expand Down Expand Up @@ -2496,6 +2497,21 @@ describe('BridgeController', function () {
const quotesByDecreasingProcessingTime = [...mockBridgeQuotesSolErc20];
quotesByDecreasingProcessingTime.reverse();

const makeQuoteRequest = (
overrides: Partial<GenericQuoteRequest> = {},
): GenericQuoteRequest => ({
walletAddress: '0x123',
srcChainId: 1,
destChainId: 10,
srcTokenAddress: '0x0000000000000000000000000000000000000000',
destTokenAddress: '0x0000000000000000000000000000000000000000',
srcTokenAmount: '1000',
slippage: 0.5,
gasIncluded: false,
gasIncluded7702: false,
...overrides,
});

beforeEach(() => {
jest.clearAllMocks();
jest
Expand Down Expand Up @@ -2727,6 +2743,33 @@ describe('BridgeController', function () {
expect(quotes).toStrictEqual(mockBridgeQuotesSolErc20);
expect(bridgeController.state).toStrictEqual(expectedControllerState);
});

it('should preserve gasSponsored flag on quotes', async () => {
const firstQuoteWithFlag: QuoteResponse = {
...mockBridgeQuotesNativeErc20Eth[0],
quote: {
...mockBridgeQuotesNativeErc20Eth[0].quote,
gasSponsored: true,
},
} as QuoteResponse;
const secondQuote: QuoteResponse =
mockBridgeQuotesNativeErc20Eth[1] as QuoteResponse;
const quotesWithFlag: QuoteResponse[] = [firstQuoteWithFlag, secondQuote];

const fetchBridgeQuotesSpy = jest
.spyOn(fetchUtils, 'fetchBridgeQuotes')
.mockResolvedValueOnce({
quotes: quotesWithFlag,
validationFailures: [],
});

const quotes = await bridgeController.fetchQuotes(makeQuoteRequest());

expect(fetchBridgeQuotesSpy).toHaveBeenCalledTimes(1);
expect(quotes).toHaveLength(2);
expect(quotes[0].quote.gasSponsored).toBe(true);
expect(quotes[1].quote.gasSponsored).toBeUndefined();
});
});

describe('metadata', () => {
Expand Down
4 changes: 4 additions & 0 deletions packages/bridge-controller/src/utils/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ export const QuoteSchema = type({
totalFeeAmountUsd: optional(string()),
}),
),
/**
* A third party sponsors the gas. If true, then gasIncluded7702 is also true.
*/
gasSponsored: optional(boolean()),
Copy link
Contributor

@stanleyyconsensys stanleyyconsensys Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit

please update the comment for gasIncluded7702, as gas sponser will also set this field to true

Copy link
Contributor

@stanleyyconsensys stanleyyconsensys Oct 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please double confirm

if gasIncluded7702 is true and gasSponsored is true

what happen to the extension when it is not ready support that from UI?

});

export const TxDataSchema = type({
Expand Down
Loading