@metamask-previews/bridge-controller 13.0.0-preview-13a1c613 → 14.0.0-preview-f919f9b0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -3
- package/dist/bridge-controller.cjs +59 -4
- package/dist/bridge-controller.cjs.map +1 -1
- package/dist/bridge-controller.d.cts +2 -3
- package/dist/bridge-controller.d.cts.map +1 -1
- package/dist/bridge-controller.d.mts +2 -3
- package/dist/bridge-controller.d.mts.map +1 -1
- package/dist/bridge-controller.mjs +60 -5
- package/dist/bridge-controller.mjs.map +1 -1
- package/dist/constants/bridge.cjs +1 -0
- package/dist/constants/bridge.cjs.map +1 -1
- package/dist/constants/bridge.d.cts.map +1 -1
- package/dist/constants/bridge.d.mts.map +1 -1
- package/dist/constants/bridge.mjs +1 -0
- package/dist/constants/bridge.mjs.map +1 -1
- package/dist/index.cjs +13 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +10 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +10 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +10 -1
- package/dist/index.mjs.map +1 -1
- package/dist/selectors.cjs +224 -0
- package/dist/selectors.cjs.map +1 -0
- package/dist/selectors.d.cts +1506 -0
- package/dist/selectors.d.cts.map +1 -0
- package/dist/selectors.d.mts +1506 -0
- package/dist/selectors.d.mts.map +1 -0
- package/dist/selectors.mjs +220 -0
- package/dist/selectors.mjs.map +1 -0
- package/dist/types.cjs.map +1 -1
- package/dist/types.d.cts +44 -14
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +44 -14
- package/dist/types.d.mts.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils/assets.cjs +30 -0
- package/dist/utils/assets.cjs.map +1 -0
- package/dist/utils/assets.d.cts +9 -0
- package/dist/utils/assets.d.cts.map +1 -0
- package/dist/utils/assets.d.mts +9 -0
- package/dist/utils/assets.d.mts.map +1 -0
- package/dist/utils/assets.mjs +25 -0
- package/dist/utils/assets.mjs.map +1 -0
- package/dist/utils/caip-formatters.cjs +25 -1
- package/dist/utils/caip-formatters.cjs.map +1 -1
- package/dist/utils/caip-formatters.d.cts +10 -0
- package/dist/utils/caip-formatters.d.cts.map +1 -1
- package/dist/utils/caip-formatters.d.mts +10 -0
- package/dist/utils/caip-formatters.d.mts.map +1 -1
- package/dist/utils/caip-formatters.mjs +25 -2
- package/dist/utils/caip-formatters.mjs.map +1 -1
- package/dist/utils/fetch.cjs +61 -1
- package/dist/utils/fetch.cjs.map +1 -1
- package/dist/utils/fetch.d.cts +21 -1
- package/dist/utils/fetch.d.cts.map +1 -1
- package/dist/utils/fetch.d.mts +21 -1
- package/dist/utils/fetch.d.mts.map +1 -1
- package/dist/utils/fetch.mjs +59 -0
- package/dist/utils/fetch.mjs.map +1 -1
- package/dist/utils/quote.cjs +177 -1
- package/dist/utils/quote.cjs.map +1 -1
- package/dist/utils/quote.d.cts +62 -1
- package/dist/utils/quote.d.cts.map +1 -1
- package/dist/utils/quote.d.mts +62 -1
- package/dist/utils/quote.d.mts.map +1 -1
- package/dist/utils/quote.mjs +164 -0
- package/dist/utils/quote.mjs.map +1 -1
- package/package.json +9 -5
package/CHANGELOG.md
CHANGED
@@ -9,8 +9,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
9
9
|
|
10
10
|
### Changed
|
11
11
|
|
12
|
-
- Bump `@metamask/snaps-
|
13
|
-
|
12
|
+
- Bump `@metamask/snaps-controllers` peer dependency from ^9.19.0 to ^11.2.1 ([#5639](https://github.com/MetaMask/core/pull/5639))
|
13
|
+
|
14
|
+
## [14.0.0]
|
15
|
+
|
16
|
+
### Added
|
17
|
+
|
18
|
+
- **BREAKING:** Add `@metamask/assets-controllers` as a required peer dependency at `^56.0.0` ([#5614](https://github.com/MetaMask/core/pull/5614))
|
19
|
+
- Add `reselect` as a dependency at `^5.1.1` ([#5614](https://github.com/MetaMask/core/pull/5614))
|
20
|
+
- **BREAKING:** assetExchangeRates added to BridgeController state to support tokens which are not supported by assets controllers ([#5614](https://github.com/MetaMask/core/pull/5614))
|
21
|
+
- selectExchangeRateByChainIdAndAddress selector added, which looks up exchange rates from assets and bridge controller states ([#5614](https://github.com/MetaMask/core/pull/5614))
|
22
|
+
- selectBridgeQuotes selector added, which returns sorted quotes including their metadata ([#5614](https://github.com/MetaMask/core/pull/5614))
|
23
|
+
- selectIsQuoteExpired selector added, which returns whether quotes are expired or stale ([#5614](https://github.com/MetaMask/core/pull/5614))
|
24
|
+
|
25
|
+
### Changed
|
26
|
+
|
27
|
+
- **BREAKING:** Change TokenAmountValues key types from BigNumber to string ([#5614](https://github.com/MetaMask/core/pull/5614))
|
28
|
+
- **BREAKING:** Assets controller getState actions have been added to `AllowedActions` so clients will need to include `TokenRatesController:getState`,`MultichainAssetsRatesController:getState` and `CurrencyRateController:getState` in controller initializations ([#5614](https://github.com/MetaMask/core/pull/5614))
|
29
|
+
- Make srcAsset and destAsset optional in Step type to be optional ([#5614](https://github.com/MetaMask/core/pull/5614))
|
30
|
+
- Make QuoteResponse trade generic to support Solana quotes which have string trade data ([#5614](https://github.com/MetaMask/core/pull/5614))
|
14
31
|
- Bump `@metamask/multichain-network-controller` peer dependency to `^0.4.0` ([#5649](https://github.com/MetaMask/core/pull/5649))
|
15
32
|
|
16
33
|
## [13.0.0]
|
@@ -127,7 +144,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
127
144
|
|
128
145
|
- Initial release ([#5317](https://github.com/MetaMask/core/pull/5317))
|
129
146
|
|
130
|
-
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@
|
147
|
+
[Unreleased]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@14.0.0...HEAD
|
148
|
+
[14.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@13.0.0...@metamask/bridge-controller@14.0.0
|
131
149
|
[13.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@12.0.0...@metamask/bridge-controller@13.0.0
|
132
150
|
[12.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@11.0.0...@metamask/bridge-controller@12.0.0
|
133
151
|
[11.0.0]: https://github.com/MetaMask/core/compare/@metamask/bridge-controller@10.0.0...@metamask/bridge-controller@11.0.0
|
@@ -10,18 +10,19 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
10
10
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
11
11
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
12
12
|
};
|
13
|
-
var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
|
13
|
+
var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_fetchAssetExchangeRates, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
15
15
|
exports.BridgeController = void 0;
|
16
16
|
const contracts_1 = require("@ethersproject/contracts");
|
17
17
|
const providers_1 = require("@ethersproject/providers");
|
18
18
|
const metamask_eth_abis_1 = require("@metamask/metamask-eth-abis");
|
19
19
|
const polling_controller_1 = require("@metamask/polling-controller");
|
20
|
-
const snaps_utils_1 = require("@metamask/snaps-utils");
|
21
20
|
const utils_1 = require("@metamask/utils");
|
22
21
|
const bridge_1 = require("./constants/bridge.cjs");
|
23
22
|
const chains_1 = require("./constants/chains.cjs");
|
23
|
+
const selectors_1 = require("./selectors.cjs");
|
24
24
|
const types_1 = require("./types.cjs");
|
25
|
+
const assets_1 = require("./utils/assets.cjs");
|
25
26
|
const balance_1 = require("./utils/balance.cjs");
|
26
27
|
const bridge_2 = require("./utils/bridge.cjs");
|
27
28
|
const caip_formatters_1 = require("./utils/caip-formatters.cjs");
|
@@ -60,6 +61,10 @@ const metadata = {
|
|
60
61
|
persist: false,
|
61
62
|
anonymous: false,
|
62
63
|
},
|
64
|
+
assetExchangeRates: {
|
65
|
+
persist: false,
|
66
|
+
anonymous: false,
|
67
|
+
},
|
63
68
|
};
|
64
69
|
const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
|
65
70
|
class BridgeController extends (0, polling_controller_1.StaticIntervalPollingController)() {
|
@@ -103,6 +108,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
103
108
|
state.quotesInitialLoadTime =
|
104
109
|
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
105
110
|
});
|
111
|
+
await __classPrivateFieldGet(this, _BridgeController_fetchAssetExchangeRates, "f").call(this, updatedQuoteRequest).catch((error) => console.warn('Failed to fetch asset exchange rates', error));
|
106
112
|
if ((0, quote_1.isValidQuoteRequest)(updatedQuoteRequest)) {
|
107
113
|
__classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
|
108
114
|
const providerConfig = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.configuration;
|
@@ -134,6 +140,52 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
134
140
|
});
|
135
141
|
}
|
136
142
|
};
|
143
|
+
/**
|
144
|
+
* Fetches the exchange rates for the assets in the quote request if they are not already in the state
|
145
|
+
* In addition to the selected tokens, this also fetches the native asset for the source and destination chains
|
146
|
+
*
|
147
|
+
* @param quoteRequest - The quote request
|
148
|
+
* @param quoteRequest.srcChainId - The source chain ID
|
149
|
+
* @param quoteRequest.srcTokenAddress - The source token address
|
150
|
+
* @param quoteRequest.destChainId - The destination chain ID
|
151
|
+
* @param quoteRequest.destTokenAddress - The destination token address
|
152
|
+
*/
|
153
|
+
_BridgeController_fetchAssetExchangeRates.set(this, async ({ srcChainId, srcTokenAddress, destChainId, destTokenAddress, }) => {
|
154
|
+
const assetIds = new Set([]);
|
155
|
+
const exchangeRateSources = {
|
156
|
+
...this.messagingSystem.call('MultichainAssetsRatesController:getState'),
|
157
|
+
...this.messagingSystem.call('CurrencyRateController:getState'),
|
158
|
+
...this.messagingSystem.call('TokenRatesController:getState'),
|
159
|
+
...this.state,
|
160
|
+
};
|
161
|
+
if (srcTokenAddress &&
|
162
|
+
srcChainId &&
|
163
|
+
!(0, selectors_1.selectIsAssetExchangeRateInState)(exchangeRateSources, srcChainId, srcTokenAddress)) {
|
164
|
+
(0, assets_1.getAssetIdsForToken)(srcTokenAddress, srcChainId).forEach((assetId) => assetIds.add(assetId));
|
165
|
+
}
|
166
|
+
if (destTokenAddress &&
|
167
|
+
destChainId &&
|
168
|
+
!(0, selectors_1.selectIsAssetExchangeRateInState)(exchangeRateSources, destChainId, destTokenAddress)) {
|
169
|
+
(0, assets_1.getAssetIdsForToken)(destTokenAddress, destChainId).forEach((assetId) => assetIds.add(assetId));
|
170
|
+
}
|
171
|
+
const currency = this.messagingSystem.call('CurrencyRateController:getState').currentCurrency;
|
172
|
+
if (assetIds.size === 0) {
|
173
|
+
return;
|
174
|
+
}
|
175
|
+
const pricesByAssetId = await (0, fetch_1.fetchAssetPrices)({
|
176
|
+
assetIds,
|
177
|
+
currencies: new Set([currency]),
|
178
|
+
clientId: __classPrivateFieldGet(this, _BridgeController_clientId, "f"),
|
179
|
+
fetchFn: __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"),
|
180
|
+
});
|
181
|
+
const exchangeRates = (0, assets_1.toExchangeRates)(currency, pricesByAssetId);
|
182
|
+
this.update((state) => {
|
183
|
+
state.assetExchangeRates = {
|
184
|
+
...state.assetExchangeRates,
|
185
|
+
...exchangeRates,
|
186
|
+
};
|
187
|
+
});
|
188
|
+
});
|
137
189
|
_BridgeController_hasSufficientBalance.set(this, async (quoteRequest) => {
|
138
190
|
const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this)?.address;
|
139
191
|
const srcChainIdInHex = (0, caip_formatters_1.formatChainIdToHex)(quoteRequest.srcChainId);
|
@@ -162,6 +214,8 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
162
214
|
state.quoteFetchError = bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
163
215
|
state.quotesRefreshCount =
|
164
216
|
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
217
|
+
state.assetExchangeRates =
|
218
|
+
bridge_1.DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;
|
165
219
|
// Keep feature flags
|
166
220
|
const originalFeatureFlags = state.bridgeFeatureFlags;
|
167
221
|
state.bridgeFeatureFlags = originalFeatureFlags;
|
@@ -293,9 +347,10 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
293
347
|
const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this);
|
294
348
|
if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {
|
295
349
|
const { value: fees } = (await this.messagingSystem.call('SnapController:handleRequest', {
|
350
|
+
// TODO fix these types
|
296
351
|
snapId: selectedAccount.metadata.snap.id,
|
297
352
|
origin: 'metamask',
|
298
|
-
handler:
|
353
|
+
handler: 'onRpcRequest',
|
299
354
|
request: {
|
300
355
|
method: 'getFeeForTransaction',
|
301
356
|
params: {
|
@@ -343,7 +398,7 @@ class BridgeController extends (0, polling_controller_1.StaticIntervalPollingCon
|
|
343
398
|
}
|
344
399
|
}
|
345
400
|
exports.BridgeController = BridgeController;
|
346
|
-
_BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
|
401
|
+
_BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_fetchAssetExchangeRates = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
|
347
402
|
return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
|
348
403
|
}, _BridgeController_getSelectedNetworkClientId = function _BridgeController_getSelectedNetworkClientId() {
|
349
404
|
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"bridge-controller.cjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport type { ChainId } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport { type SnapId } from '@metamask/snaps-sdk';\nimport { HandlerType } from '@metamask/snaps-utils';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport { numberToHex } from '@metamask/utils';\nimport type { Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\n DEFAULT_BRIDGE_CONTROLLER_STATE,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP,\n REFRESH_INTERVAL_MS,\n} from './constants/bridge';\nimport { CHAIN_IDS } from './constants/chains';\nimport type { GenericQuoteRequest, SolanaFees } from './types';\nimport {\n type L1GasFees,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n type BridgeControllerMessenger,\n type FetchFunction,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport { hasSufficientBalance } from './utils/balance';\nimport {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\nimport { fetchBridgeFeatureFlags, fetchBridgeQuotes } from './utils/fetch';\nimport { isValidQuoteRequest } from './utils/quote';\n\nconst metadata: StateMetadata<BridgeControllerState> = {\n bridgeFeatureFlags: {\n persist: false,\n anonymous: false,\n },\n quoteRequest: {\n persist: false,\n anonymous: false,\n },\n quotes: {\n persist: false,\n anonymous: false,\n },\n quotesInitialLoadTime: {\n persist: false,\n anonymous: false,\n },\n quotesLastFetched: {\n persist: false,\n anonymous: false,\n },\n quotesLoadingStatus: {\n persist: false,\n anonymous: false,\n },\n quoteFetchError: {\n persist: false,\n anonymous: false,\n },\n quotesRefreshCount: {\n persist: false,\n anonymous: false,\n },\n};\n\nconst RESET_STATE_ABORT_MESSAGE = 'Reset controller state';\n\n/** The input to start polling for the {@link BridgeController} */\ntype BridgePollingInput = {\n networkClientId: NetworkClientId;\n updatedQuoteRequest: GenericQuoteRequest;\n};\n\nexport class BridgeController extends StaticIntervalPollingController<BridgePollingInput>()<\n typeof BRIDGE_CONTROLLER_NAME,\n BridgeControllerState,\n BridgeControllerMessenger\n> {\n #abortController: AbortController | undefined;\n\n #quotesFirstFetched: number | undefined;\n\n readonly #clientId: string;\n\n readonly #getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\n }: {\n messenger: BridgeControllerMessenger;\n state?: Partial<BridgeControllerState>;\n clientId: BridgeClientId;\n getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n fetchFn: FetchFunction;\n config?: {\n customBridgeApiBaseUrl?: string;\n };\n }) {\n super({\n name: BRIDGE_CONTROLLER_NAME,\n metadata,\n messenger,\n state: {\n ...getDefaultBridgeControllerState(),\n ...state,\n },\n });\n\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.#abortController = new AbortController();\n this.#getLayer1GasFee = getLayer1GasFee;\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#config = config ?? {};\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,\n this.setBridgeFeatureFlags.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`,\n this.updateBridgeQuoteRequestParams.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`,\n this.getBridgeERC20Allowance.bind(this),\n );\n }\n\n _executePoll = async (pollingInput: BridgePollingInput) => {\n await this.#fetchBridgeQuotes(pollingInput);\n };\n\n updateBridgeQuoteRequestParams = async (\n paramsToUpdate: Partial<GenericQuoteRequest>,\n ) => {\n this.stopAllPolling();\n this.#abortController?.abort('Quote request updated');\n\n const updatedQuoteRequest = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,\n ...paramsToUpdate,\n };\n\n this.update((state) => {\n state.quoteRequest = updatedQuoteRequest;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n });\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\n quoteRequest.srcTokenAmount,\n srcChainIdInHex,\n ))\n );\n };\n\n resetState = () => {\n this.stopAllPolling();\n this.#abortController?.abort(RESET_STATE_ABORT_MESSAGE);\n\n this.update((state) => {\n // Cannot do direct assignment to state, i.e. state = {... }, need to manually assign each field\n state.quoteRequest = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n\n // Keep feature flags\n const originalFeatureFlags = state.bridgeFeatureFlags;\n state.bridgeFeatureFlags = originalFeatureFlags;\n });\n };\n\n setBridgeFeatureFlags = async () => {\n const bridgeFeatureFlags = await fetchBridgeFeatureFlags(\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\n };\n\n readonly #fetchBridgeQuotes = async ({\n networkClientId: _networkClientId,\n updatedQuoteRequest,\n }: BridgePollingInput) => {\n const { bridgeFeatureFlags, quotesInitialLoadTime, quotesRefreshCount } =\n this.state;\n this.#abortController?.abort('New quote request');\n this.#abortController = new AbortController();\n\n this.update((state) => {\n state.quotesLoadingStatus = RequestStatus.LOADING;\n state.quoteRequest = updatedQuoteRequest;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n });\n\n try {\n const quotes = await fetchBridgeQuotes(\n updatedQuoteRequest,\n // AbortController is always defined by this line, because we assign it a few lines above,\n // not sure why Jest thinks it's not\n // Linters accurately say that it's defined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#abortController!.signal as AbortSignal,\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\n state.quotesLoadingStatus = RequestStatus.FETCHED;\n });\n } catch (error) {\n const isAbortError = (error as Error).name === 'AbortError';\n const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;\n if (isAbortedDueToReset || isAbortError) {\n return;\n }\n\n this.update((state) => {\n state.quoteFetchError =\n error instanceof Error ? error.message : 'Unknown error';\n state.quotesLoadingStatus = RequestStatus.ERROR;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n });\n console.log('Failed to fetch bridge quotes', error);\n } finally {\n const { maxRefreshCount } =\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];\n\n const updatedQuotesRefreshCount = quotesRefreshCount + 1;\n // Stop polling if the maximum number of refreshes has been reached\n if (\n updatedQuoteRequest.insufficientBal ||\n (!updatedQuoteRequest.insufficientBal &&\n updatedQuotesRefreshCount >= maxRefreshCount)\n ) {\n this.stopAllPolling();\n }\n\n // Update quote fetching stats\n const quotesLastFetched = Date.now();\n this.update((state) => {\n state.quotesInitialLoadTime =\n updatedQuotesRefreshCount === 1 && this.#quotesFirstFetched\n ? quotesLastFetched - this.#quotesFirstFetched\n : quotesInitialLoadTime;\n state.quotesLastFetched = quotesLastFetched;\n state.quotesRefreshCount = updatedQuotesRefreshCount;\n });\n }\n };\n\n readonly #appendL1GasFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & L1GasFees)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { quote, trade, approval } = quoteResponse;\n const chainId = numberToHex(quote.srcChainId) as ChainId;\n\n const getTxParams = (txData: TxData) => ({\n from: txData.from,\n to: txData.to,\n value: txData.value,\n data: txData.data,\n gasLimit: txData.gasLimit?.toString(),\n });\n const approvalL1GasFees = approval\n ? await this.#getLayer1GasFee({\n transactionParams: getTxParams(approval),\n chainId,\n })\n : '0';\n const tradeL1GasFees = await this.#getLayer1GasFee({\n transactionParams: getTxParams(trade),\n chainId,\n });\n return {\n ...quoteResponse,\n l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),\n };\n }),\n );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n snapId: selectedAccount.metadata.snap.id as SnapId,\n origin: 'metamask',\n handler: HandlerType.OnRpcRequest,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\n }\n\n /**\n *\n * @param contractAddress - The address of the ERC20 token contract\n * @param chainId - The hex chain ID of the bridge network\n * @returns The atomic allowance of the ERC20 token contract\n */\n getBridgeERC20Allowance = async (\n contractAddress: string,\n chainId: Hex,\n ): Promise<string> => {\n const provider = this.#getSelectedNetworkClient()?.provider;\n if (!provider) {\n throw new Error('No provider found');\n }\n\n const ethersProvider = new Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
|
1
|
+
{"version":3,"file":"bridge-controller.cjs","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import type { BigNumber } from '@ethersproject/bignumber';\nimport { Contract } from '@ethersproject/contracts';\nimport { Web3Provider } from '@ethersproject/providers';\nimport type { StateMetadata } from '@metamask/base-controller';\nimport type { ChainId } from '@metamask/controller-utils';\nimport { abiERC20 } from '@metamask/metamask-eth-abis';\nimport type { NetworkClientId } from '@metamask/network-controller';\nimport { StaticIntervalPollingController } from '@metamask/polling-controller';\nimport type { TransactionParams } from '@metamask/transaction-controller';\nimport type { CaipAssetType } from '@metamask/utils';\nimport { numberToHex, type Hex } from '@metamask/utils';\n\nimport {\n type BridgeClientId,\n BRIDGE_CONTROLLER_NAME,\n BRIDGE_PROD_API_BASE_URL,\n DEFAULT_BRIDGE_CONTROLLER_STATE,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP,\n REFRESH_INTERVAL_MS,\n} from './constants/bridge';\nimport { CHAIN_IDS } from './constants/chains';\nimport { selectIsAssetExchangeRateInState } from './selectors';\nimport {\n type L1GasFees,\n type GenericQuoteRequest,\n type SolanaFees,\n type QuoteResponse,\n type TxData,\n type BridgeControllerState,\n type BridgeControllerMessenger,\n type FetchFunction,\n BridgeFeatureFlagsKey,\n RequestStatus,\n} from './types';\nimport { getAssetIdsForToken, toExchangeRates } from './utils/assets';\nimport { hasSufficientBalance } from './utils/balance';\nimport {\n getDefaultBridgeControllerState,\n isSolanaChainId,\n sumHexes,\n} from './utils/bridge';\nimport {\n formatAddressToCaipReference,\n formatChainIdToCaip,\n formatChainIdToHex,\n} from './utils/caip-formatters';\nimport {\n fetchAssetPrices,\n fetchBridgeFeatureFlags,\n fetchBridgeQuotes,\n} from './utils/fetch';\nimport { isValidQuoteRequest } from './utils/quote';\n\nconst metadata: StateMetadata<BridgeControllerState> = {\n bridgeFeatureFlags: {\n persist: false,\n anonymous: false,\n },\n quoteRequest: {\n persist: false,\n anonymous: false,\n },\n quotes: {\n persist: false,\n anonymous: false,\n },\n quotesInitialLoadTime: {\n persist: false,\n anonymous: false,\n },\n quotesLastFetched: {\n persist: false,\n anonymous: false,\n },\n quotesLoadingStatus: {\n persist: false,\n anonymous: false,\n },\n quoteFetchError: {\n persist: false,\n anonymous: false,\n },\n quotesRefreshCount: {\n persist: false,\n anonymous: false,\n },\n assetExchangeRates: {\n persist: false,\n anonymous: false,\n },\n};\n\nconst RESET_STATE_ABORT_MESSAGE = 'Reset controller state';\n\n/** The input to start polling for the {@link BridgeController} */\ntype BridgePollingInput = {\n networkClientId: NetworkClientId;\n updatedQuoteRequest: GenericQuoteRequest;\n};\n\nexport class BridgeController extends StaticIntervalPollingController<BridgePollingInput>()<\n typeof BRIDGE_CONTROLLER_NAME,\n BridgeControllerState,\n BridgeControllerMessenger\n> {\n #abortController: AbortController | undefined;\n\n #quotesFirstFetched: number | undefined;\n\n readonly #clientId: string;\n\n readonly #getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n\n readonly #fetchFn: FetchFunction;\n\n readonly #config: {\n customBridgeApiBaseUrl?: string;\n };\n\n constructor({\n messenger,\n state,\n clientId,\n getLayer1GasFee,\n fetchFn,\n config,\n }: {\n messenger: BridgeControllerMessenger;\n state?: Partial<BridgeControllerState>;\n clientId: BridgeClientId;\n getLayer1GasFee: (params: {\n transactionParams: TransactionParams;\n chainId: ChainId;\n }) => Promise<string>;\n fetchFn: FetchFunction;\n config?: {\n customBridgeApiBaseUrl?: string;\n };\n }) {\n super({\n name: BRIDGE_CONTROLLER_NAME,\n metadata,\n messenger,\n state: {\n ...getDefaultBridgeControllerState(),\n ...state,\n },\n });\n\n this.setIntervalLength(REFRESH_INTERVAL_MS);\n\n this.#abortController = new AbortController();\n this.#getLayer1GasFee = getLayer1GasFee;\n this.#clientId = clientId;\n this.#fetchFn = fetchFn;\n this.#config = config ?? {};\n\n // Register action handlers\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:setBridgeFeatureFlags`,\n this.setBridgeFeatureFlags.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:updateBridgeQuoteRequestParams`,\n this.updateBridgeQuoteRequestParams.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:resetState`,\n this.resetState.bind(this),\n );\n this.messagingSystem.registerActionHandler(\n `${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`,\n this.getBridgeERC20Allowance.bind(this),\n );\n }\n\n _executePoll = async (pollingInput: BridgePollingInput) => {\n await this.#fetchBridgeQuotes(pollingInput);\n };\n\n updateBridgeQuoteRequestParams = async (\n paramsToUpdate: Partial<GenericQuoteRequest>,\n ) => {\n this.stopAllPolling();\n this.#abortController?.abort('Quote request updated');\n\n const updatedQuoteRequest = {\n ...DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest,\n ...paramsToUpdate,\n };\n\n this.update((state) => {\n state.quoteRequest = updatedQuoteRequest;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n });\n\n await this.#fetchAssetExchangeRates(updatedQuoteRequest).catch((error) =>\n console.warn('Failed to fetch asset exchange rates', error),\n );\n\n if (isValidQuoteRequest(updatedQuoteRequest)) {\n this.#quotesFirstFetched = Date.now();\n const providerConfig = this.#getSelectedNetworkClient()?.configuration;\n\n let insufficientBal: boolean | undefined;\n if (isSolanaChainId(updatedQuoteRequest.srcChainId)) {\n // If the source chain is not an EVM network, use value from params\n insufficientBal = paramsToUpdate.insufficientBal;\n } else if (providerConfig?.rpcUrl?.includes('tenderly')) {\n // If the rpcUrl is a tenderly fork (e2e tests), set insufficientBal=true\n // The bridge-api filters out quotes if the balance on mainnet is insufficient so this override allows quotes to always be returned\n insufficientBal = true;\n } else {\n // Otherwise query the src token balance from the RPC provider\n insufficientBal =\n paramsToUpdate.insufficientBal ??\n !(await this.#hasSufficientBalance(updatedQuoteRequest));\n }\n\n const networkClientId = this.#getSelectedNetworkClientId();\n // Set refresh rate based on the source chain before starting polling\n this.#setIntervalLength();\n this.startPolling({\n networkClientId,\n updatedQuoteRequest: {\n ...updatedQuoteRequest,\n insufficientBal,\n },\n });\n }\n };\n\n /**\n * Fetches the exchange rates for the assets in the quote request if they are not already in the state\n * In addition to the selected tokens, this also fetches the native asset for the source and destination chains\n *\n * @param quoteRequest - The quote request\n * @param quoteRequest.srcChainId - The source chain ID\n * @param quoteRequest.srcTokenAddress - The source token address\n * @param quoteRequest.destChainId - The destination chain ID\n * @param quoteRequest.destTokenAddress - The destination token address\n */\n readonly #fetchAssetExchangeRates = async ({\n srcChainId,\n srcTokenAddress,\n destChainId,\n destTokenAddress,\n }: Partial<GenericQuoteRequest>) => {\n const assetIds: Set<CaipAssetType> = new Set([]);\n\n const exchangeRateSources = {\n ...this.messagingSystem.call('MultichainAssetsRatesController:getState'),\n ...this.messagingSystem.call('CurrencyRateController:getState'),\n ...this.messagingSystem.call('TokenRatesController:getState'),\n ...this.state,\n };\n\n if (\n srcTokenAddress &&\n srcChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n srcChainId,\n srcTokenAddress,\n )\n ) {\n getAssetIdsForToken(srcTokenAddress, srcChainId).forEach((assetId) =>\n assetIds.add(assetId),\n );\n }\n if (\n destTokenAddress &&\n destChainId &&\n !selectIsAssetExchangeRateInState(\n exchangeRateSources,\n destChainId,\n destTokenAddress,\n )\n ) {\n getAssetIdsForToken(destTokenAddress, destChainId).forEach((assetId) =>\n assetIds.add(assetId),\n );\n }\n\n const currency = this.messagingSystem.call(\n 'CurrencyRateController:getState',\n ).currentCurrency;\n\n if (assetIds.size === 0) {\n return;\n }\n\n const pricesByAssetId = await fetchAssetPrices({\n assetIds,\n currencies: new Set([currency]),\n clientId: this.#clientId,\n fetchFn: this.#fetchFn,\n });\n const exchangeRates = toExchangeRates(currency, pricesByAssetId);\n this.update((state) => {\n state.assetExchangeRates = {\n ...state.assetExchangeRates,\n ...exchangeRates,\n };\n });\n };\n\n readonly #hasSufficientBalance = async (\n quoteRequest: GenericQuoteRequest,\n ) => {\n const walletAddress = this.#getMultichainSelectedAccount()?.address;\n const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);\n const provider = this.#getSelectedNetworkClient()?.provider;\n const normalizedSrcTokenAddress = formatAddressToCaipReference(\n quoteRequest.srcTokenAddress,\n );\n\n return (\n provider &&\n walletAddress &&\n normalizedSrcTokenAddress &&\n quoteRequest.srcTokenAmount &&\n srcChainIdInHex &&\n (await hasSufficientBalance(\n provider,\n walletAddress,\n normalizedSrcTokenAddress,\n quoteRequest.srcTokenAmount,\n srcChainIdInHex,\n ))\n );\n };\n\n resetState = () => {\n this.stopAllPolling();\n this.#abortController?.abort(RESET_STATE_ABORT_MESSAGE);\n\n this.update((state) => {\n // Cannot do direct assignment to state, i.e. state = {... }, need to manually assign each field\n state.quoteRequest = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteRequest;\n state.quotesInitialLoadTime =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n state.quotesLastFetched =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLastFetched;\n state.quotesLoadingStatus =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesLoadingStatus;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n state.quotesRefreshCount =\n DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;\n state.assetExchangeRates =\n DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;\n\n // Keep feature flags\n const originalFeatureFlags = state.bridgeFeatureFlags;\n state.bridgeFeatureFlags = originalFeatureFlags;\n });\n };\n\n setBridgeFeatureFlags = async () => {\n const bridgeFeatureFlags = await fetchBridgeFeatureFlags(\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n this.update((state) => {\n state.bridgeFeatureFlags = bridgeFeatureFlags;\n });\n this.#setIntervalLength();\n };\n\n /**\n * Sets the interval length based on the source chain\n */\n readonly #setIntervalLength = () => {\n const { state } = this;\n const { srcChainId } = state.quoteRequest;\n const refreshRateOverride = srcChainId\n ? state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG].chains[\n formatChainIdToCaip(srcChainId)\n ]?.refreshRate\n : undefined;\n const defaultRefreshRate =\n state.bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG]\n .refreshRate;\n this.setIntervalLength(refreshRateOverride ?? defaultRefreshRate);\n };\n\n readonly #fetchBridgeQuotes = async ({\n networkClientId: _networkClientId,\n updatedQuoteRequest,\n }: BridgePollingInput) => {\n const { bridgeFeatureFlags, quotesInitialLoadTime, quotesRefreshCount } =\n this.state;\n this.#abortController?.abort('New quote request');\n this.#abortController = new AbortController();\n\n this.update((state) => {\n state.quotesLoadingStatus = RequestStatus.LOADING;\n state.quoteRequest = updatedQuoteRequest;\n state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;\n });\n\n try {\n const quotes = await fetchBridgeQuotes(\n updatedQuoteRequest,\n // AbortController is always defined by this line, because we assign it a few lines above,\n // not sure why Jest thinks it's not\n // Linters accurately say that it's defined\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n this.#abortController!.signal as AbortSignal,\n this.#clientId,\n this.#fetchFn,\n this.#config.customBridgeApiBaseUrl ?? BRIDGE_PROD_API_BASE_URL,\n );\n\n const quotesWithL1GasFees = await this.#appendL1GasFees(quotes);\n const quotesWithSolanaFees = await this.#appendSolanaFees(quotes);\n\n this.update((state) => {\n state.quotes = quotesWithL1GasFees ?? quotesWithSolanaFees ?? quotes;\n state.quotesLoadingStatus = RequestStatus.FETCHED;\n });\n } catch (error) {\n const isAbortError = (error as Error).name === 'AbortError';\n const isAbortedDueToReset = error === RESET_STATE_ABORT_MESSAGE;\n if (isAbortedDueToReset || isAbortError) {\n return;\n }\n\n this.update((state) => {\n state.quoteFetchError =\n error instanceof Error ? error.message : 'Unknown error';\n state.quotesLoadingStatus = RequestStatus.ERROR;\n state.quotes = DEFAULT_BRIDGE_CONTROLLER_STATE.quotes;\n });\n console.log('Failed to fetch bridge quotes', error);\n } finally {\n const { maxRefreshCount } =\n bridgeFeatureFlags[BridgeFeatureFlagsKey.EXTENSION_CONFIG];\n\n const updatedQuotesRefreshCount = quotesRefreshCount + 1;\n // Stop polling if the maximum number of refreshes has been reached\n if (\n updatedQuoteRequest.insufficientBal ||\n (!updatedQuoteRequest.insufficientBal &&\n updatedQuotesRefreshCount >= maxRefreshCount)\n ) {\n this.stopAllPolling();\n }\n\n // Update quote fetching stats\n const quotesLastFetched = Date.now();\n this.update((state) => {\n state.quotesInitialLoadTime =\n updatedQuotesRefreshCount === 1 && this.#quotesFirstFetched\n ? quotesLastFetched - this.#quotesFirstFetched\n : quotesInitialLoadTime;\n state.quotesLastFetched = quotesLastFetched;\n state.quotesRefreshCount = updatedQuotesRefreshCount;\n });\n }\n };\n\n readonly #appendL1GasFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & L1GasFees)[] | undefined> => {\n // Indicates whether some of the quotes are not for optimism or base\n const hasInvalidQuotes = quotes.some(({ quote }) => {\n const chainId = formatChainIdToCaip(quote.srcChainId);\n return ![CHAIN_IDS.OPTIMISM, CHAIN_IDS.BASE]\n .map(formatChainIdToCaip)\n .includes(chainId);\n });\n\n // Only append L1 gas fees if all quotes are for either optimism or base\n if (!hasInvalidQuotes) {\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { quote, trade, approval } = quoteResponse;\n const chainId = numberToHex(quote.srcChainId) as ChainId;\n\n const getTxParams = (txData: TxData) => ({\n from: txData.from,\n to: txData.to,\n value: txData.value,\n data: txData.data,\n gasLimit: txData.gasLimit?.toString(),\n });\n const approvalL1GasFees = approval\n ? await this.#getLayer1GasFee({\n transactionParams: getTxParams(approval),\n chainId,\n })\n : '0';\n const tradeL1GasFees = await this.#getLayer1GasFee({\n transactionParams: getTxParams(trade),\n chainId,\n });\n return {\n ...quoteResponse,\n l1GasFeesInHexWei: sumHexes(approvalL1GasFees, tradeL1GasFees),\n };\n }),\n );\n }\n\n return undefined;\n };\n\n readonly #appendSolanaFees = async (\n quotes: QuoteResponse[],\n ): Promise<(QuoteResponse & SolanaFees)[] | undefined> => {\n // Return early if some of the quotes are not for solana\n if (\n quotes.some(({ quote: { srcChainId } }) => !isSolanaChainId(srcChainId))\n ) {\n return undefined;\n }\n\n return await Promise.all(\n quotes.map(async (quoteResponse) => {\n const { trade } = quoteResponse;\n const selectedAccount = this.#getMultichainSelectedAccount();\n\n if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {\n const { value: fees } = (await this.messagingSystem.call(\n 'SnapController:handleRequest',\n {\n // TODO fix these types\n snapId: selectedAccount.metadata.snap.id as never,\n origin: 'metamask',\n handler: 'onRpcRequest' as never,\n request: {\n method: 'getFeeForTransaction',\n params: {\n transaction: trade,\n scope: selectedAccount.options.scope,\n },\n },\n },\n )) as { value: string };\n\n return {\n ...quoteResponse,\n solanaFeesInLamports: fees,\n };\n }\n return quoteResponse;\n }),\n );\n };\n\n #getMultichainSelectedAccount() {\n return this.messagingSystem.call(\n 'AccountsController:getSelectedMultichainAccount',\n );\n }\n\n #getSelectedNetworkClientId() {\n const { selectedNetworkClientId } = this.messagingSystem.call(\n 'NetworkController:getState',\n );\n return selectedNetworkClientId;\n }\n\n #getSelectedNetworkClient() {\n const selectedNetworkClientId = this.#getSelectedNetworkClientId();\n const networkClient = this.messagingSystem.call(\n 'NetworkController:getNetworkClientById',\n selectedNetworkClientId,\n );\n return networkClient;\n }\n\n /**\n *\n * @param contractAddress - The address of the ERC20 token contract\n * @param chainId - The hex chain ID of the bridge network\n * @returns The atomic allowance of the ERC20 token contract\n */\n getBridgeERC20Allowance = async (\n contractAddress: string,\n chainId: Hex,\n ): Promise<string> => {\n const provider = this.#getSelectedNetworkClient()?.provider;\n if (!provider) {\n throw new Error('No provider found');\n }\n\n const ethersProvider = new Web3Provider(provider);\n const contract = new Contract(contractAddress, abiERC20, ethersProvider);\n const { address: walletAddress } =\n this.#getMultichainSelectedAccount() ?? {};\n const allowance: BigNumber = await contract.allowance(\n walletAddress,\n METABRIDGE_CHAIN_TO_ADDRESS_MAP[chainId],\n );\n return allowance.toString();\n };\n}\n"]}
|
@@ -1,10 +1,9 @@
|
|
1
1
|
import type { ChainId } from "@metamask/controller-utils";
|
2
2
|
import type { NetworkClientId } from "@metamask/network-controller";
|
3
3
|
import type { TransactionParams } from "@metamask/transaction-controller";
|
4
|
-
import type
|
4
|
+
import { type Hex } from "@metamask/utils";
|
5
5
|
import { type BridgeClientId, BRIDGE_CONTROLLER_NAME } from "./constants/bridge.cjs";
|
6
|
-
import type
|
7
|
-
import { type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.cjs";
|
6
|
+
import { type GenericQuoteRequest, type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.cjs";
|
8
7
|
/** The input to start polling for the {@link BridgeController} */
|
9
8
|
type BridgePollingInput = {
|
10
9
|
networkClientId: NetworkClientId;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;
|
1
|
+
{"version":3,"file":"bridge-controller.d.cts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,EAAe,KAAK,GAAG,EAAE,wBAAwB;AAExD,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAG5B,OAAO,EAEL,KAAK,mBAAmB,EAIxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA6DjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,EAAE;QACD,SAAS,EAAE,yBAAyB,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,EAAE,CAAC,MAAM,EAAE;YACxB,iBAAiB,EAAE,iBAAiB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC;SAClB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,aAAa,CAAC;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBA0D5C;IAuGF,UAAU,aAwBR;IAEF,qBAAqB,sBAUnB;IA8MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
|
@@ -1,10 +1,9 @@
|
|
1
1
|
import type { ChainId } from "@metamask/controller-utils";
|
2
2
|
import type { NetworkClientId } from "@metamask/network-controller";
|
3
3
|
import type { TransactionParams } from "@metamask/transaction-controller";
|
4
|
-
import type
|
4
|
+
import { type Hex } from "@metamask/utils";
|
5
5
|
import { type BridgeClientId, BRIDGE_CONTROLLER_NAME } from "./constants/bridge.mjs";
|
6
|
-
import type
|
7
|
-
import { type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.mjs";
|
6
|
+
import { type GenericQuoteRequest, type BridgeControllerState, type BridgeControllerMessenger, type FetchFunction } from "./types.mjs";
|
8
7
|
/** The input to start polling for the {@link BridgeController} */
|
9
8
|
type BridgePollingInput = {
|
10
9
|
networkClientId: NetworkClientId;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;
|
1
|
+
{"version":3,"file":"bridge-controller.d.mts","sourceRoot":"","sources":["../src/bridge-controller.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,OAAO,EAAE,mCAAmC;AAE1D,OAAO,KAAK,EAAE,eAAe,EAAE,qCAAqC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,yCAAyC;AAE1E,OAAO,EAAe,KAAK,GAAG,EAAE,wBAAwB;AAExD,OAAO,EACL,KAAK,cAAc,EACnB,sBAAsB,EAKvB,+BAA2B;AAG5B,OAAO,EAEL,KAAK,mBAAmB,EAIxB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,aAAa,EAGnB,oBAAgB;AA6DjB,kEAAkE;AAClE,KAAK,kBAAkB,GAAG;IACxB,eAAe,EAAE,eAAe,CAAC;IACjC,mBAAmB,EAAE,mBAAmB,CAAC;CAC1C,CAAC;;;;;;;;;;;;;;;;AAEF,qBAAa,gBAAiB,SAAQ,sBACpC,OAAO,sBAAsB,EAC7B,qBAAqB,EACrB,yBAAyB,CAC1B;;gBAkBa,EACV,SAAS,EACT,KAAK,EACL,QAAQ,EACR,eAAe,EACf,OAAO,EACP,MAAM,GACP,EAAE;QACD,SAAS,EAAE,yBAAyB,CAAC;QACrC,KAAK,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;QACvC,QAAQ,EAAE,cAAc,CAAC;QACzB,eAAe,EAAE,CAAC,MAAM,EAAE;YACxB,iBAAiB,EAAE,iBAAiB,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC;SAClB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,aAAa,CAAC;QACvB,MAAM,CAAC,EAAE;YACP,sBAAsB,CAAC,EAAE,MAAM,CAAC;SACjC,CAAC;KACH;IAsCD,YAAY,iBAAwB,kBAAkB,mBAEpD;IAEF,8BAA8B,mBACZ,QAAQ,mBAAmB,CAAC,mBA0D5C;IAuGF,UAAU,aAwBR;IAEF,qBAAqB,sBAUnB;IA8MF;;;;;OAKG;IACH,uBAAuB,oBACJ,MAAM,WACd,GAAG,KACX,QAAQ,MAAM,CAAC,CAehB;CACH"}
|
@@ -9,20 +9,21 @@ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (
|
|
9
9
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
10
10
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
11
11
|
};
|
12
|
-
var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
|
12
|
+
var _BridgeController_instances, _BridgeController_abortController, _BridgeController_quotesFirstFetched, _BridgeController_clientId, _BridgeController_getLayer1GasFee, _BridgeController_fetchFn, _BridgeController_config, _BridgeController_fetchAssetExchangeRates, _BridgeController_hasSufficientBalance, _BridgeController_setIntervalLength, _BridgeController_fetchBridgeQuotes, _BridgeController_appendL1GasFees, _BridgeController_appendSolanaFees, _BridgeController_getMultichainSelectedAccount, _BridgeController_getSelectedNetworkClientId, _BridgeController_getSelectedNetworkClient;
|
13
13
|
import { Contract } from "@ethersproject/contracts";
|
14
14
|
import { Web3Provider } from "@ethersproject/providers";
|
15
15
|
import { abiERC20 } from "@metamask/metamask-eth-abis";
|
16
16
|
import { StaticIntervalPollingController } from "@metamask/polling-controller";
|
17
|
-
import { HandlerType } from "@metamask/snaps-utils";
|
18
17
|
import { numberToHex } from "@metamask/utils";
|
19
18
|
import { BRIDGE_CONTROLLER_NAME, BRIDGE_PROD_API_BASE_URL, DEFAULT_BRIDGE_CONTROLLER_STATE, METABRIDGE_CHAIN_TO_ADDRESS_MAP, REFRESH_INTERVAL_MS } from "./constants/bridge.mjs";
|
20
19
|
import { CHAIN_IDS } from "./constants/chains.mjs";
|
20
|
+
import { selectIsAssetExchangeRateInState } from "./selectors.mjs";
|
21
21
|
import { BridgeFeatureFlagsKey, RequestStatus } from "./types.mjs";
|
22
|
+
import { getAssetIdsForToken, toExchangeRates } from "./utils/assets.mjs";
|
22
23
|
import { hasSufficientBalance } from "./utils/balance.mjs";
|
23
24
|
import { getDefaultBridgeControllerState, isSolanaChainId, sumHexes } from "./utils/bridge.mjs";
|
24
25
|
import { formatAddressToCaipReference, formatChainIdToCaip, formatChainIdToHex } from "./utils/caip-formatters.mjs";
|
25
|
-
import { fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
|
26
|
+
import { fetchAssetPrices, fetchBridgeFeatureFlags, fetchBridgeQuotes } from "./utils/fetch.mjs";
|
26
27
|
import { isValidQuoteRequest } from "./utils/quote.mjs";
|
27
28
|
const metadata = {
|
28
29
|
bridgeFeatureFlags: {
|
@@ -57,6 +58,10 @@ const metadata = {
|
|
57
58
|
persist: false,
|
58
59
|
anonymous: false,
|
59
60
|
},
|
61
|
+
assetExchangeRates: {
|
62
|
+
persist: false,
|
63
|
+
anonymous: false,
|
64
|
+
},
|
60
65
|
};
|
61
66
|
const RESET_STATE_ABORT_MESSAGE = 'Reset controller state';
|
62
67
|
export class BridgeController extends StaticIntervalPollingController() {
|
@@ -100,6 +105,7 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
100
105
|
state.quotesInitialLoadTime =
|
101
106
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesInitialLoadTime;
|
102
107
|
});
|
108
|
+
await __classPrivateFieldGet(this, _BridgeController_fetchAssetExchangeRates, "f").call(this, updatedQuoteRequest).catch((error) => console.warn('Failed to fetch asset exchange rates', error));
|
103
109
|
if (isValidQuoteRequest(updatedQuoteRequest)) {
|
104
110
|
__classPrivateFieldSet(this, _BridgeController_quotesFirstFetched, Date.now(), "f");
|
105
111
|
const providerConfig = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getSelectedNetworkClient).call(this)?.configuration;
|
@@ -131,6 +137,52 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
131
137
|
});
|
132
138
|
}
|
133
139
|
};
|
140
|
+
/**
|
141
|
+
* Fetches the exchange rates for the assets in the quote request if they are not already in the state
|
142
|
+
* In addition to the selected tokens, this also fetches the native asset for the source and destination chains
|
143
|
+
*
|
144
|
+
* @param quoteRequest - The quote request
|
145
|
+
* @param quoteRequest.srcChainId - The source chain ID
|
146
|
+
* @param quoteRequest.srcTokenAddress - The source token address
|
147
|
+
* @param quoteRequest.destChainId - The destination chain ID
|
148
|
+
* @param quoteRequest.destTokenAddress - The destination token address
|
149
|
+
*/
|
150
|
+
_BridgeController_fetchAssetExchangeRates.set(this, async ({ srcChainId, srcTokenAddress, destChainId, destTokenAddress, }) => {
|
151
|
+
const assetIds = new Set([]);
|
152
|
+
const exchangeRateSources = {
|
153
|
+
...this.messagingSystem.call('MultichainAssetsRatesController:getState'),
|
154
|
+
...this.messagingSystem.call('CurrencyRateController:getState'),
|
155
|
+
...this.messagingSystem.call('TokenRatesController:getState'),
|
156
|
+
...this.state,
|
157
|
+
};
|
158
|
+
if (srcTokenAddress &&
|
159
|
+
srcChainId &&
|
160
|
+
!selectIsAssetExchangeRateInState(exchangeRateSources, srcChainId, srcTokenAddress)) {
|
161
|
+
getAssetIdsForToken(srcTokenAddress, srcChainId).forEach((assetId) => assetIds.add(assetId));
|
162
|
+
}
|
163
|
+
if (destTokenAddress &&
|
164
|
+
destChainId &&
|
165
|
+
!selectIsAssetExchangeRateInState(exchangeRateSources, destChainId, destTokenAddress)) {
|
166
|
+
getAssetIdsForToken(destTokenAddress, destChainId).forEach((assetId) => assetIds.add(assetId));
|
167
|
+
}
|
168
|
+
const currency = this.messagingSystem.call('CurrencyRateController:getState').currentCurrency;
|
169
|
+
if (assetIds.size === 0) {
|
170
|
+
return;
|
171
|
+
}
|
172
|
+
const pricesByAssetId = await fetchAssetPrices({
|
173
|
+
assetIds,
|
174
|
+
currencies: new Set([currency]),
|
175
|
+
clientId: __classPrivateFieldGet(this, _BridgeController_clientId, "f"),
|
176
|
+
fetchFn: __classPrivateFieldGet(this, _BridgeController_fetchFn, "f"),
|
177
|
+
});
|
178
|
+
const exchangeRates = toExchangeRates(currency, pricesByAssetId);
|
179
|
+
this.update((state) => {
|
180
|
+
state.assetExchangeRates = {
|
181
|
+
...state.assetExchangeRates,
|
182
|
+
...exchangeRates,
|
183
|
+
};
|
184
|
+
});
|
185
|
+
});
|
134
186
|
_BridgeController_hasSufficientBalance.set(this, async (quoteRequest) => {
|
135
187
|
const walletAddress = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this)?.address;
|
136
188
|
const srcChainIdInHex = formatChainIdToHex(quoteRequest.srcChainId);
|
@@ -159,6 +211,8 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
159
211
|
state.quoteFetchError = DEFAULT_BRIDGE_CONTROLLER_STATE.quoteFetchError;
|
160
212
|
state.quotesRefreshCount =
|
161
213
|
DEFAULT_BRIDGE_CONTROLLER_STATE.quotesRefreshCount;
|
214
|
+
state.assetExchangeRates =
|
215
|
+
DEFAULT_BRIDGE_CONTROLLER_STATE.assetExchangeRates;
|
162
216
|
// Keep feature flags
|
163
217
|
const originalFeatureFlags = state.bridgeFeatureFlags;
|
164
218
|
state.bridgeFeatureFlags = originalFeatureFlags;
|
@@ -290,9 +344,10 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
290
344
|
const selectedAccount = __classPrivateFieldGet(this, _BridgeController_instances, "m", _BridgeController_getMultichainSelectedAccount).call(this);
|
291
345
|
if (selectedAccount?.metadata?.snap?.id && typeof trade === 'string') {
|
292
346
|
const { value: fees } = (await this.messagingSystem.call('SnapController:handleRequest', {
|
347
|
+
// TODO fix these types
|
293
348
|
snapId: selectedAccount.metadata.snap.id,
|
294
349
|
origin: 'metamask',
|
295
|
-
handler:
|
350
|
+
handler: 'onRpcRequest',
|
296
351
|
request: {
|
297
352
|
method: 'getFeeForTransaction',
|
298
353
|
params: {
|
@@ -339,7 +394,7 @@ export class BridgeController extends StaticIntervalPollingController() {
|
|
339
394
|
this.messagingSystem.registerActionHandler(`${BRIDGE_CONTROLLER_NAME}:getBridgeERC20Allowance`, this.getBridgeERC20Allowance.bind(this));
|
340
395
|
}
|
341
396
|
}
|
342
|
-
_BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
|
397
|
+
_BridgeController_abortController = new WeakMap(), _BridgeController_quotesFirstFetched = new WeakMap(), _BridgeController_clientId = new WeakMap(), _BridgeController_getLayer1GasFee = new WeakMap(), _BridgeController_fetchFn = new WeakMap(), _BridgeController_config = new WeakMap(), _BridgeController_fetchAssetExchangeRates = new WeakMap(), _BridgeController_hasSufficientBalance = new WeakMap(), _BridgeController_setIntervalLength = new WeakMap(), _BridgeController_fetchBridgeQuotes = new WeakMap(), _BridgeController_appendL1GasFees = new WeakMap(), _BridgeController_appendSolanaFees = new WeakMap(), _BridgeController_instances = new WeakSet(), _BridgeController_getMultichainSelectedAccount = function _BridgeController_getMultichainSelectedAccount() {
|
343
398
|
return this.messagingSystem.call('AccountsController:getSelectedMultichainAccount');
|
344
399
|
}, _BridgeController_getSelectedNetworkClientId = function _BridgeController_getSelectedNetworkClientId() {
|
345
400
|
const { selectedNetworkClientId } = this.messagingSystem.call('NetworkController:getState');
|