diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index d0beac1ca52..19497bb46be 100644 --- a/packages/bridge-controller/CHANGELOG.md +++ b/packages/bridge-controller/CHANGELOG.md @@ -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)) diff --git a/packages/bridge-controller/src/bridge-controller.test.ts b/packages/bridge-controller/src/bridge-controller.test.ts index 3ead2e8f47d..cebdfbbe9a6 100644 --- a/packages/bridge-controller/src/bridge-controller.test.ts +++ b/packages/bridge-controller/src/bridge-controller.test.ts @@ -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'; @@ -2496,6 +2497,21 @@ describe('BridgeController', function () { const quotesByDecreasingProcessingTime = [...mockBridgeQuotesSolErc20]; quotesByDecreasingProcessingTime.reverse(); + const makeQuoteRequest = ( + overrides: Partial = {}, + ): 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 @@ -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', () => { diff --git a/packages/bridge-controller/src/utils/validators.ts b/packages/bridge-controller/src/utils/validators.ts index 5d5507b6225..ae8729a1296 100644 --- a/packages/bridge-controller/src/utils/validators.ts +++ b/packages/bridge-controller/src/utils/validators.ts @@ -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()), }); export const TxDataSchema = type({