From 59f7c1d53b3a389bc0243d37669c31981d309106 Mon Sep 17 00:00:00 2001 From: salimtb Date: Mon, 2 Mar 2026 17:50:00 +0100 Subject: [PATCH 1/6] fix: use new controller on bridge --- packages/bridge-controller/package.json | 1 + .../src/bridge-controller.ts | 42 +++++++++-- packages/bridge-controller/src/selectors.ts | 71 ++++++++++++++----- packages/bridge-controller/src/types.ts | 4 +- .../bridge-controller/tsconfig.build.json | 3 +- packages/bridge-controller/tsconfig.json | 3 +- yarn.lock | 3 +- 7 files changed, 99 insertions(+), 28 deletions(-) diff --git a/packages/bridge-controller/package.json b/packages/bridge-controller/package.json index 18f3c7dcefa..b3a06a43299 100644 --- a/packages/bridge-controller/package.json +++ b/packages/bridge-controller/package.json @@ -53,6 +53,7 @@ "@ethersproject/contracts": "^5.7.0", "@ethersproject/providers": "^5.7.0", "@metamask/accounts-controller": "^36.0.1", + "@metamask/assets-controller": "^2.2.0", "@metamask/assets-controllers": "^100.0.3", "@metamask/base-controller": "^9.0.0", "@metamask/controller-utils": "^11.19.0", diff --git a/packages/bridge-controller/src/bridge-controller.ts b/packages/bridge-controller/src/bridge-controller.ts index 1ed63030a80..9283439c5e5 100644 --- a/packages/bridge-controller/src/bridge-controller.ts +++ b/packages/bridge-controller/src/bridge-controller.ts @@ -21,7 +21,10 @@ import { import { CHAIN_IDS } from './constants/chains'; import { SWAPS_CONTRACT_ADDRESSES } from './constants/swaps'; import { TraceName } from './constants/traces'; -import { selectIsAssetExchangeRateInState } from './selectors'; +import { + ExchangeRateSourcesForLookup, + selectIsAssetExchangeRateInState, +} from './selectors'; import { RequestStatus } from './types'; import type { L1GasFees, @@ -196,6 +199,13 @@ export class BridgeController extends StaticIntervalPollingController; @@ -224,6 +235,12 @@ export class BridgeController extends StaticIntervalPollingController, ) => void; traceFn?: TraceCallback; + /** + * When true, use AssetsController for exchange rates (assetsPrice, currentCurrency) + * instead of MultichainAssetsRatesController, TokenRatesController, and + * CurrencyRateController. Requires AssetsController:getState to be registered. + */ + useAssetsControllerForRates?: boolean; }) { super({ name: BRIDGE_CONTROLLER_NAME, @@ -245,6 +262,7 @@ export class BridgeController extends StaticIntervalPollingController fn?.()) as TraceCallback); + this.#useAssetsControllerForRates = useAssetsControllerForRates ?? false; // Register action handlers this.messenger.registerActionHandler( @@ -399,13 +417,24 @@ export class BridgeController extends StaticIntervalPollingController { - return { + readonly #getExchangeRateSources = (): ExchangeRateSourcesForLookup => { + if (this.#useAssetsControllerForRates) { + const res = { + ...this.messenger.call('AssetsController:getExchangeRatesForBridge'), + historicalPrices: {}, + ...this.state, + }; + console.log('res ++++++++++++++', JSON.stringify(res, null, 2)); + return res; + } + const res2 = { ...this.messenger.call('MultichainAssetsRatesController:getState'), ...this.messenger.call('CurrencyRateController:getState'), ...this.messenger.call('TokenRatesController:getState'), ...this.state, }; + console.log('res2 ++++++++++++++', JSON.stringify(res2, null, 2)); + return res2; }; /** @@ -453,9 +482,10 @@ export class BridgeController extends StaticIntervalPollingController & + Partial> & + Partial> & { + marketData?: + | TokenRatesControllerState['marketData'] + | Record>; + conversionRates?: + | MultichainAssetsRatesControllerState['conversionRates'] + | Record; + }; + export type BridgeAppState = BridgeControllerState & { gasFeeEstimatesByChainId: GasFeeEstimatesByChainId; } & ExchangeRateControllerState & { @@ -122,7 +141,7 @@ export const selectBridgeFeatureFlags = createFeatureFlagsSelector( ); const getExchangeRateByChainIdAndAddress = ( - exchangeRateSources: ExchangeRateControllerState, + exchangeRateSources: ExchangeRateSourcesForLookup, chainId?: GenericQuoteRequest['srcChainId'], rawAddress?: GenericQuoteRequest['srcTokenAddress'], ): ExchangeRate => { @@ -151,27 +170,35 @@ const getExchangeRateByChainIdAndAddress = ( } // If the chain is a non-EVM chain, use the conversion rate from the multichain assets controller if (isNonEvmChainId(chainId)) { - const multichainAssetExchangeRate = conversionRates?.[assetId]; - if (multichainAssetExchangeRate) { + const conversionRatesByKey = conversionRates as + | Record + | undefined; + const multichainAssetExchangeRate = conversionRatesByKey?.[assetId]; + const rate = multichainAssetExchangeRate?.rate; + if (rate) { // The multichain rate is denominated in the user's selected currency. // To get a USD rate, find the user's-currency-to-USD conversion factor from any EVM native currency rate. const nativeCurrencyRate = Object.values(currencyRates ?? {}).find( - (rate) => rate?.conversionRate && rate?.usdConversionRate, + (rateEntry) => + rateEntry?.conversionRate !== undefined && + rateEntry?.conversionRate !== null && + rateEntry?.usdConversionRate !== undefined && + rateEntry?.usdConversionRate !== null, ); const usersCurrencyToUsdRate = - nativeCurrencyRate?.conversionRate && - nativeCurrencyRate?.usdConversionRate + nativeCurrencyRate?.conversionRate !== undefined && + nativeCurrencyRate?.conversionRate !== null && + nativeCurrencyRate?.usdConversionRate !== undefined && + nativeCurrencyRate?.usdConversionRate !== null ? new BigNumber(nativeCurrencyRate.usdConversionRate).div( nativeCurrencyRate.conversionRate, ) : undefined; const usdExchangeRate = usersCurrencyToUsdRate - ? new BigNumber(multichainAssetExchangeRate.rate) - .times(usersCurrencyToUsdRate) - .toString() + ? new BigNumber(rate).times(usersCurrencyToUsdRate).toString() : undefined; return { - exchangeRate: multichainAssetExchangeRate.rate, + exchangeRate: rate, usdExchangeRate, }; } @@ -183,27 +210,35 @@ const getExchangeRateByChainIdAndAddress = ( const evmNativeExchangeRate = currencyRates?.[symbol]; if (evmNativeExchangeRate) { return { - exchangeRate: evmNativeExchangeRate?.conversionRate?.toString(), - usdExchangeRate: evmNativeExchangeRate?.usdConversionRate?.toString(), + exchangeRate: evmNativeExchangeRate.conversionRate?.toString(), + usdExchangeRate: evmNativeExchangeRate.usdConversionRate?.toString(), }; } return {}; } // If the chain is an EVM chain and the asset is not the native asset, use the conversion rate from the token rates controller if (!isNonEvmChainId(chainId)) { - const evmTokenExchangeRates = marketData?.[formatChainIdToHex(chainId)]; + const marketDataByChain = + (marketData as + | Record> + | undefined) ?? {}; + const evmTokenExchangeRates = + marketDataByChain[formatChainIdToHex(chainId)]; const evmTokenExchangeRateForAddress = isStrictHexString(address) ? evmTokenExchangeRates?.[address] : null; - const nativeCurrencyRate = evmTokenExchangeRateForAddress - ? currencyRates[evmTokenExchangeRateForAddress?.currency] - : undefined; + const currencyKey = evmTokenExchangeRateForAddress?.currency; + const nativeCurrencyRate = + currencyKey !== undefined && currencyKey !== null + ? currencyRates?.[currencyKey] + : undefined; + const price = evmTokenExchangeRateForAddress?.price ?? 0; if (evmTokenExchangeRateForAddress && nativeCurrencyRate) { return { - exchangeRate: new BigNumber(evmTokenExchangeRateForAddress.price) + exchangeRate: new BigNumber(price) .multipliedBy(nativeCurrencyRate.conversionRate ?? 0) .toString(), - usdExchangeRate: new BigNumber(evmTokenExchangeRateForAddress.price) + usdExchangeRate: new BigNumber(price) .multipliedBy(nativeCurrencyRate.usdConversionRate ?? 0) .toString(), }; diff --git a/packages/bridge-controller/src/types.ts b/packages/bridge-controller/src/types.ts index 41217d8578c..12d265eb5b5 100644 --- a/packages/bridge-controller/src/types.ts +++ b/packages/bridge-controller/src/types.ts @@ -1,4 +1,5 @@ import type { AccountsControllerGetAccountByAddressAction } from '@metamask/accounts-controller'; +import type { AssetsControllerGetExchangeRatesForBridgeAction } from '@metamask/assets-controller'; import type { GetCurrencyRateState, MultichainAssetsRatesControllerGetStateAction, @@ -400,7 +401,8 @@ export type AllowedActions = | HandleSnapRequest | NetworkControllerFindNetworkClientIdByChainIdAction | NetworkControllerGetNetworkClientByIdAction - | RemoteFeatureFlagControllerGetStateAction; + | RemoteFeatureFlagControllerGetStateAction + | AssetsControllerGetExchangeRatesForBridgeAction; export type AllowedEvents = never; /** diff --git a/packages/bridge-controller/tsconfig.build.json b/packages/bridge-controller/tsconfig.build.json index 33bbb3a6dc8..a8f7180477a 100644 --- a/packages/bridge-controller/tsconfig.build.json +++ b/packages/bridge-controller/tsconfig.build.json @@ -15,7 +15,8 @@ { "path": "../assets-controllers/tsconfig.build.json" }, { "path": "../transaction-controller/tsconfig.build.json" }, { "path": "../multichain-network-controller/tsconfig.build.json" }, - { "path": "../remote-feature-flag-controller/tsconfig.build.json" } + { "path": "../remote-feature-flag-controller/tsconfig.build.json" }, + { "path": "../assets-controller/tsconfig.build.json" } ], "include": ["../../types", "./src"] } diff --git a/packages/bridge-controller/tsconfig.json b/packages/bridge-controller/tsconfig.json index 61896deae83..fd36e969bd5 100644 --- a/packages/bridge-controller/tsconfig.json +++ b/packages/bridge-controller/tsconfig.json @@ -15,7 +15,8 @@ { "path": "../assets-controllers" }, { "path": "../multichain-network-controller" }, { "path": "../profile-sync-controller" }, - { "path": "../remote-feature-flag-controller" } + { "path": "../remote-feature-flag-controller" }, + { "path": "../assets-controller" } ], "include": ["../../types", "./src", "./tests"] } diff --git a/yarn.lock b/yarn.lock index 93a254cf438..2cf1daefca6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2511,7 +2511,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/assets-controller@workspace:packages/assets-controller": +"@metamask/assets-controller@npm:^2.2.0, @metamask/assets-controller@workspace:packages/assets-controller": version: 0.0.0-use.local resolution: "@metamask/assets-controller@workspace:packages/assets-controller" dependencies: @@ -2742,6 +2742,7 @@ __metadata: "@ethersproject/contracts": "npm:^5.7.0" "@ethersproject/providers": "npm:^5.7.0" "@metamask/accounts-controller": "npm:^36.0.1" + "@metamask/assets-controller": "npm:^2.2.0" "@metamask/assets-controllers": "npm:^100.0.3" "@metamask/auto-changelog": "npm:^3.4.4" "@metamask/base-controller": "npm:^9.0.0" From 28accf058747e4bc5f7bd40ef58981593bd0ff50 Mon Sep 17 00:00:00 2001 From: salimtb Date: Mon, 2 Mar 2026 23:55:34 +0100 Subject: [PATCH 2/6] fix: clean up --- .../src/bridge-controller.test.ts | 230 ++++++++++++++++++ .../src/bridge-controller.ts | 28 +-- 2 files changed, 244 insertions(+), 14 deletions(-) diff --git a/packages/bridge-controller/src/bridge-controller.test.ts b/packages/bridge-controller/src/bridge-controller.test.ts index e696b1af665..a1d90843629 100644 --- a/packages/bridge-controller/src/bridge-controller.test.ts +++ b/packages/bridge-controller/src/bridge-controller.test.ts @@ -144,6 +144,236 @@ describe('BridgeController', function () { expect(bridgeController.state).toStrictEqual(EMPTY_INIT_STATE); }); + describe('getExchangeRateSources and fetchAssetExchangeRates', function () { + it('calls MultichainAssetsRatesController, CurrencyRateController, and TokenRatesController when useAssetsControllerForRates is false', async function () { + jest.useFakeTimers(); + const hasSufficientBalanceSpy = jest + .spyOn(balanceUtils, 'hasSufficientBalance') + .mockResolvedValue(true); + + const getStateReturn = { + conversionRates: {}, + currencyRates: {}, + marketData: {}, + currentCurrency: 'USD', + }; + messengerMock.call.mockImplementation( + (actionType: string): ReturnType => { + if (actionType === 'AuthenticationController:getBearerToken') { + return 'AUTH_TOKEN'; + } + if ( + actionType === 'MultichainAssetsRatesController:getState' || + actionType === 'CurrencyRateController:getState' || + actionType === 'TokenRatesController:getState' + ) { + return getStateReturn as never; + } + return { + remoteFeatureFlags: { bridgeConfig: { ...bridgeConfig } }, + address: '0x123', + provider: jest.fn(), + } as never; + }, + ); + + const selectIsAssetExchangeRateInStateSpy = jest.spyOn( + selectors, + 'selectIsAssetExchangeRateInState', + ); + + await bridgeController.updateBridgeQuoteRequestParams( + { + srcChainId: '0x1', + destChainId: '0xa', + srcTokenAddress: '0x0000000000000000000000000000000000000000', + destTokenAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + srcTokenAmount: '1000000000000000000', + walletAddress: '0x123', + slippage: 0.5, + }, + metricsContext, + ); + + jest.advanceTimersToNextTimer(); + await flushPromises(); + + expect(messengerMock.call).toHaveBeenCalledWith( + 'MultichainAssetsRatesController:getState', + ); + expect(messengerMock.call).toHaveBeenCalledWith( + 'CurrencyRateController:getState', + ); + expect(messengerMock.call).toHaveBeenCalledWith( + 'TokenRatesController:getState', + ); + expect(messengerMock.call).not.toHaveBeenCalledWith( + 'AssetsController:getExchangeRatesForBridge', + ); + + expect(selectIsAssetExchangeRateInStateSpy).toHaveBeenCalled(); + const [firstCallSources] = + selectIsAssetExchangeRateInStateSpy.mock.calls[0]; + expect(firstCallSources).toHaveProperty('assetExchangeRates'); + expect(firstCallSources).toHaveProperty('conversionRates'); + expect(firstCallSources).toHaveProperty('currencyRates'); + expect(firstCallSources).toHaveProperty('marketData'); + + hasSufficientBalanceSpy.mockRestore(); + selectIsAssetExchangeRateInStateSpy.mockRestore(); + }); + + it('calls AssetsController:getExchangeRatesForBridge when getUseAssetsControllerForRates returns true', async function () { + jest.useFakeTimers(); + const controllerWithAssetsRates = new BridgeController({ + messenger: messengerMock, + getLayer1GasFee: getLayer1GasFeeMock, + clientId: BridgeClientId.EXTENSION, + clientVersion: '13.7.0', + fetchFn: mockFetchFn, + trackMetaMetricsFn, + getUseAssetsControllerForRates: () => true, + }); + controllerWithAssetsRates.resetState(); + + const hasSufficientBalanceSpy = jest + .spyOn(balanceUtils, 'hasSufficientBalance') + .mockResolvedValue(true); + + const bridgeRatesReturn = { + conversionRates: {}, + currencyRates: {}, + marketData: {}, + currentCurrency: 'EUR', + }; + messengerMock.call.mockImplementation( + (actionType: string): ReturnType => { + if (actionType === 'AuthenticationController:getBearerToken') { + return 'AUTH_TOKEN'; + } + if (actionType === 'AssetsController:getExchangeRatesForBridge') { + return bridgeRatesReturn as never; + } + return { + remoteFeatureFlags: { bridgeConfig: { ...bridgeConfig } }, + address: '0x123', + provider: jest.fn(), + } as never; + }, + ); + + const selectIsAssetExchangeRateInStateSpy = jest.spyOn( + selectors, + 'selectIsAssetExchangeRateInState', + ); + + await controllerWithAssetsRates.updateBridgeQuoteRequestParams( + { + srcChainId: '0x1', + destChainId: '0xa', + srcTokenAddress: '0x0000000000000000000000000000000000000000', + destTokenAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + srcTokenAmount: '1000000000000000000', + walletAddress: '0x123', + slippage: 0.5, + }, + metricsContext, + ); + + jest.advanceTimersToNextTimer(); + await flushPromises(); + + expect(messengerMock.call).toHaveBeenCalledWith( + 'AssetsController:getExchangeRatesForBridge', + ); + expect(messengerMock.call).not.toHaveBeenCalledWith( + 'MultichainAssetsRatesController:getState', + ); + + expect(selectIsAssetExchangeRateInStateSpy).toHaveBeenCalled(); + const [firstCallSources] = + selectIsAssetExchangeRateInStateSpy.mock.calls[0]; + expect(firstCallSources).toHaveProperty('assetExchangeRates'); + expect(firstCallSources).toHaveProperty('currentCurrency', 'EUR'); + + hasSufficientBalanceSpy.mockRestore(); + selectIsAssetExchangeRateInStateSpy.mockRestore(); + }); + + it('calls selectIsAssetExchangeRateInState with exchange rate sources, src chain/address, and dest chain/address', async function () { + jest.useFakeTimers(); + const hasSufficientBalanceSpy = jest + .spyOn(balanceUtils, 'hasSufficientBalance') + .mockResolvedValue(true); + + messengerMock.call.mockImplementation( + (actionType: string): ReturnType => { + if (actionType === 'AuthenticationController:getBearerToken') { + return 'AUTH_TOKEN'; + } + if ( + actionType === 'MultichainAssetsRatesController:getState' || + actionType === 'CurrencyRateController:getState' || + actionType === 'TokenRatesController:getState' + ) { + return { + conversionRates: {}, + currencyRates: {}, + marketData: {}, + currentCurrency: 'USD', + } as never; + } + return { + remoteFeatureFlags: { bridgeConfig: { ...bridgeConfig } }, + address: '0x123', + provider: jest.fn(), + } as never; + }, + ); + + const selectIsAssetExchangeRateInStateSpy = jest.spyOn( + selectors, + 'selectIsAssetExchangeRateInState', + ); + + const quoteParams = { + srcChainId: '0x1', + destChainId: '0xa', + srcTokenAddress: '0x0000000000000000000000000000000000000000', + destTokenAddress: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + srcTokenAmount: '1000000000000000000', + walletAddress: '0x123', + slippage: 0.5, + }; + + await bridgeController.updateBridgeQuoteRequestParams( + quoteParams, + metricsContext, + ); + + jest.advanceTimersToNextTimer(); + await flushPromises(); + + expect(selectIsAssetExchangeRateInStateSpy).toHaveBeenCalledWith( + expect.objectContaining({ + assetExchangeRates: expect.any(Object), + }), + quoteParams.srcChainId, + quoteParams.srcTokenAddress, + ); + expect(selectIsAssetExchangeRateInStateSpy).toHaveBeenCalledWith( + expect.objectContaining({ + assetExchangeRates: expect.any(Object), + }), + quoteParams.destChainId, + quoteParams.destTokenAddress, + ); + + hasSufficientBalanceSpy.mockRestore(); + selectIsAssetExchangeRateInStateSpy.mockRestore(); + }); + }); + it('setBridgeFeatureFlags should fetch and set the bridge feature flags', async function () { const remoteFeatureFlagControllerState = { cacheTimestamp: 1745515389440, diff --git a/packages/bridge-controller/src/bridge-controller.ts b/packages/bridge-controller/src/bridge-controller.ts index 9283439c5e5..790be7a2d31 100644 --- a/packages/bridge-controller/src/bridge-controller.ts +++ b/packages/bridge-controller/src/bridge-controller.ts @@ -200,11 +200,12 @@ export class BridgeController extends StaticIntervalPollingController boolean; constructor({ messenger, @@ -216,7 +217,7 @@ export class BridgeController extends StaticIntervalPollingController; @@ -236,11 +237,11 @@ export class BridgeController extends StaticIntervalPollingController void; traceFn?: TraceCallback; /** - * When true, use AssetsController for exchange rates (assetsPrice, currentCurrency) - * instead of MultichainAssetsRatesController, TokenRatesController, and - * CurrencyRateController. Requires AssetsController:getState to be registered. + * When provided, called to determine whether to use AssetsController for exchange rates. + * When true, rates are read from AssetsController:getExchangeRatesForBridge instead of + * MultichainAssetsRatesController, TokenRatesController, and CurrencyRateController. */ - useAssetsControllerForRates?: boolean; + getUseAssetsControllerForRates?: () => boolean; }) { super({ name: BRIDGE_CONTROLLER_NAME, @@ -262,7 +263,8 @@ export class BridgeController extends StaticIntervalPollingController fn?.()) as TraceCallback); - this.#useAssetsControllerForRates = useAssetsControllerForRates ?? false; + this.#getUseAssetsControllerForRates = + getUseAssetsControllerForRates ?? (() => false); // Register action handlers this.messenger.registerActionHandler( @@ -418,13 +420,12 @@ export class BridgeController extends StaticIntervalPollingController { - if (this.#useAssetsControllerForRates) { + if (this.#getUseAssetsControllerForRates()) { const res = { ...this.messenger.call('AssetsController:getExchangeRatesForBridge'), historicalPrices: {}, ...this.state, }; - console.log('res ++++++++++++++', JSON.stringify(res, null, 2)); return res; } const res2 = { @@ -433,7 +434,6 @@ export class BridgeController extends StaticIntervalPollingController Date: Tue, 3 Mar 2026 00:02:08 +0100 Subject: [PATCH 3/6] fix: clean up --- .../src/bridge-controller.test.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/bridge-controller/src/bridge-controller.test.ts b/packages/bridge-controller/src/bridge-controller.test.ts index a1d90843629..b2b5805fca2 100644 --- a/packages/bridge-controller/src/bridge-controller.test.ts +++ b/packages/bridge-controller/src/bridge-controller.test.ts @@ -91,6 +91,15 @@ const bridgeConfig = { }, }; +const metricsContext = { + token_symbol_source: 'ETH', + token_symbol_destination: 'USDC', + usd_amount_source: 100, + stx_enabled: true, + security_warnings: [], + warnings: [], +}; + describe('BridgeController', function () { let bridgeController: BridgeController; @@ -232,7 +241,7 @@ describe('BridgeController', function () { clientVersion: '13.7.0', fetchFn: mockFetchFn, trackMetaMetricsFn, - getUseAssetsControllerForRates: () => true, + getUseAssetsControllerForRates: (): boolean => true, }); controllerWithAssetsRates.resetState(); @@ -436,15 +445,6 @@ describe('BridgeController', function () { expect(setIntervalLengthSpy).toHaveBeenCalledWith(3); }); - const metricsContext = { - token_symbol_source: 'ETH', - token_symbol_destination: 'USDC', - usd_amount_source: 100, - stx_enabled: true, - security_warnings: [], - warnings: [], - }; - it('updateBridgeQuoteRequestParams should update the quoteRequest state', async function () { messengerMock.call.mockReturnValue({ currentCurrency: 'usd', From fedcf23d4835072b31e4b33a2591ff8755051f8b Mon Sep 17 00:00:00 2001 From: salimtb Date: Tue, 3 Mar 2026 00:16:39 +0100 Subject: [PATCH 4/6] fix: clean up --- packages/assets-controllers/package.json | 2 +- packages/bridge-controller/src/bridge-controller.ts | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index e341d0acf42..246aa7966ca 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/assets-controllers", - "version": "100.0.3", + "version": "100.0.2", "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)", "keywords": [ "MetaMask", diff --git a/packages/bridge-controller/src/bridge-controller.ts b/packages/bridge-controller/src/bridge-controller.ts index 790be7a2d31..42ec4f0e95f 100644 --- a/packages/bridge-controller/src/bridge-controller.ts +++ b/packages/bridge-controller/src/bridge-controller.ts @@ -421,20 +421,18 @@ export class BridgeController extends StaticIntervalPollingController { if (this.#getUseAssetsControllerForRates()) { - const res = { + return { ...this.messenger.call('AssetsController:getExchangeRatesForBridge'), historicalPrices: {}, ...this.state, }; - return res; } - const res2 = { + return { ...this.messenger.call('MultichainAssetsRatesController:getState'), ...this.messenger.call('CurrencyRateController:getState'), ...this.messenger.call('TokenRatesController:getState'), ...this.state, }; - return res2; }; /** From 5ea9a6ec652d3348e935d261404b30913143e981 Mon Sep 17 00:00:00 2001 From: salimtb Date: Tue, 3 Mar 2026 00:36:31 +0100 Subject: [PATCH 5/6] fix: add changelog --- packages/bridge-controller/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/bridge-controller/CHANGELOG.md b/packages/bridge-controller/CHANGELOG.md index 67106800ce8..17164c9f8af 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 + +- Optional constructor option `getUseAssetsControllerForRates`: when it returns true, exchange rates are read from the new `@metamask/assets-controller` (`AssetsController:getExchangeRatesForBridge`) instead of `MultichainAssetsRatesController`, `TokenRatesController`, and `CurrencyRateController`. ([#8090](https://github.com/MetaMask/core/pull/8090)) + ## [67.4.0] ### Changed From d9398bcb17c30ca022465dd2728299ef7ea9ec42 Mon Sep 17 00:00:00 2001 From: salimtb Date: Tue, 3 Mar 2026 00:41:28 +0100 Subject: [PATCH 6/6] fix: clean up --- packages/assets-controllers/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index 246aa7966ca..e341d0acf42 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -1,6 +1,6 @@ { "name": "@metamask/assets-controllers", - "version": "100.0.2", + "version": "100.0.3", "description": "Controllers which manage interactions involving ERC-20, ERC-721, and ERC-1155 tokens (including NFTs)", "keywords": [ "MetaMask",